Merge branch 'main' of https://github.com/appwrite/website into eldad-comment-fixes

This commit is contained in:
Torsten Dittmann
2023-09-28 02:51:34 +02:00
122 changed files with 1224 additions and 516 deletions

View File

@@ -8,6 +8,7 @@ env:
TAG: ${{ github.event.release.tag_name }}
STACK_FILE: docker/production.yml
REPOSITORY: website
REGISTRY_USERNAME: christyjacob4
jobs:
build:
@@ -58,6 +59,6 @@ jobs:
echo "_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${{ secrets.APP_SYSTEM_SECURITY_EMAIL_ADDRESS }}" >> .env
echo "SEMATEXT_TOKEN=${{ secrets.SEMATEXT_TOKEN }}" >> .env
echo ${{ secrets.GH_REGISTRY_TOKEN }} | docker login ghcr.io --username ${{ github.actor }} --password-stdin
echo ${{ secrets.GH_REGISTRY_TOKEN }} | docker login ghcr.io --username ${{ env.REGISTRY_USERNAME }} --password-stdin
docker-compose -f ${{ env.STACK_FILE }} config
env $(cat .env | xargs) docker stack deploy --prune --resolve-image always --with-registry-auth -c ${{ env.STACK_FILE }} ${{ env.REPOSITORY }}

View File

@@ -9,6 +9,7 @@ env:
TAG: ${{ github.sha }}
STACK_FILE: docker/stage.yml
REPOSITORY: website
REGISTRY_USERNAME: christyjacob4
jobs:
build:
@@ -59,6 +60,6 @@ jobs:
echo "_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${{ secrets.APP_SYSTEM_SECURITY_EMAIL_ADDRESS }}" >> .env
echo "SEMATEXT_TOKEN=${{ secrets.SEMATEXT_TOKEN }}" >> .env
echo ${{ secrets.GH_REGISTRY_TOKEN }} | docker login ghcr.io --username ${{ github.actor }} --password-stdin
echo ${{ secrets.GH_REGISTRY_TOKEN }} | docker login ghcr.io --username ${{ env.REGISTRY_USERNAME }} --password-stdin
docker-compose -f ${{ env.STACK_FILE }} config
env $(cat .env | xargs) docker stack deploy --prune --resolve-image always --with-registry-auth -c ${{ env.STACK_FILE }} ${{ env.REPOSITORY }}

View File

@@ -35,7 +35,7 @@
"sharp": "^0.32.6",
"svelte": "^4.2.0",
"svelte-check": "^3.5.1",
"svelte-markdoc-preprocess": "^0.3.2",
"svelte-markdoc-preprocess": "^1.0.0",
"svelte-sequential-preprocessor": "^2.0.1",
"svgo": "^3.0.2",
"svgtofont": "^4.0.0",

8
pnpm-lock.yaml generated
View File

@@ -92,8 +92,8 @@ devDependencies:
specifier: ^3.5.1
version: 3.5.1(postcss@8.4.27)(sass@1.66.1)(svelte@4.2.0)
svelte-markdoc-preprocess:
specifier: ^0.3.2
version: 0.3.2
specifier: ^1.0.0
version: 1.0.0
svelte-sequential-preprocessor:
specifier: ^2.0.1
version: 2.0.1
@@ -4327,8 +4327,8 @@ packages:
svelte: 4.2.0
dev: true
/svelte-markdoc-preprocess@0.3.2:
resolution: {integrity: sha512-OZAH7WsFRjO3Nt0VfNaqw8Mpem6w1sMBs36PBDmKE7BoV6hoCEXEY+yQAzAHo3qrt4WZRWn5WoFad+q6xOKs3g==}
/svelte-markdoc-preprocess@1.0.0:
resolution: {integrity: sha512-vFYqUXuX0ONHeZhn0MTplS22CKsidhLAoHfX5OceX8rhmKWyKwg/R579iYNb/RDW7OyLA5UU9UCLdNhEoQ5s/w==}
dependencies:
'@markdoc/markdoc': 0.3.2
html-escaper: 3.0.3

View File

@@ -1,23 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/images/logos/logo.svg" />
<link rel="stylesheet" href="/icon-font/aw-icon.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="twitter:site" content="@appwrite" />
<meta name="twitter:site" content="@appwrite" />
%sveltekit.head%
</head>
<body class="theme-dark" data-sveltekit-preload-data="hover">
<script
type="module"
src="https://unpkg.com/@splinetool/viewer@0.9.455/build/spline-viewer.js"
></script>
<script>
const isDocs = window.location.pathname.startsWith('/docs');
if (isDocs) {
const theme = localStorage.getItem('theme');
document.body.classList.remove('theme-dark', 'theme-light') || 'dark';
document.body.classList.remove('theme-dark', 'theme-light');
if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
@@ -26,9 +24,10 @@
} else {
document.body.classList.add(`theme-${theme}`);
}
localStorage.setItem('theme', theme);
}
</script>
<script type="module" src="https://unpkg.com/@splinetool/viewer@0.9.455/build/spline-viewer.js"></script>
<div id="top" style="display: contents">%sveltekit.body%</div>
</body>
</html>

638
src/hooks/redirects.json Normal file
View File

@@ -0,0 +1,638 @@
[
{
"link": "/docs/getting-started-for-web",
"redirect": "/docs/quick-starts"
},
{
"link": "/docs/getting-started-for-flutter",
"redirect": "/docs/quick-starts/flutter"
},
{
"link": "/docs/getting-started-for-apple",
"redirect": "/docs/quick-starts/apple"
},
{
"link": "/docs/getting-started-for-android",
"redirect": "/docs/quick-starts/android"
},
{
"link": "/docs/getting-started-for-server",
"redirect": "/docs/getting-started-for-server"
},
{
"link": "/docs/self-hosting",
"redirect": "/docs/advanced/self-hosting"
},
{
"link": "/docs/client/databases",
"redirect": "/docs/references/cloud/client-web/databases"
},
{
"link": "/docs/client/account",
"redirect": "/docs/references/cloud/client-web/account"
},
{
"link": "/docs/client/storage",
"redirect": "/docs/references/cloud/client-web/storage"
},
{
"link": "/docs/functions",
"redirect": "/docs/products/functions"
},
{
"link": "/docs/realtime",
"redirect": "/docs/apis/realtime"
},
{
"link": "/docs/command-line",
"redirect": "/docs/tooling/command-line/installation"
},
{
"link": "/docs/command-line-deployment",
"redirect": "/docs/tooling/command-line/deployment"
},
{
"link": "/docs/command-line-commands",
"redirect": "/docs/tooling/command-line/commands"
},
{
"link": "/docs/command-line-ci",
"redirect": "/docs/tooling/command-line/non-interactive"
},
{
"link": "/docs/rest",
"redirect": "/docs/apis/rest"
},
{
"link": "/docs/graphql",
"redirect": "/docs/apis/graphql"
},
{
"link": "/docs/server/users",
"redirect": "/docs/references/cloud/server-nodejs/users"
},
{
"link": "/docs/client/teams",
"redirect": "/docs/references/cloud/client-web/teams"
},
{
"link": "/docs/client/functions",
"redirect": "/docs/references/cloud/client-web/functions"
},
{
"link": "/docs/client/locale",
"redirect": "/docs/references/cloud/client-web/locale"
},
{
"link": "/docs/client/avatars",
"redirect": "/docs/references/cloud/client-web/avatars"
},
{
"link": "/docs/databases",
"redirect": "/docs/products/databases"
},
{
"link": "/docs/databases-queries",
"redirect": "/docs/products/databases/queries"
},
{
"link": "/docs/databases-pagination",
"redirect": "/docs/products/databases/pagination"
},
{
"link": "/docs/databases-relationships",
"redirect": "/docs/products/databases/relationships"
},
{
"link": "/docs/storage",
"redirect": "/docs/products/storage"
},
{
"link": "/docs/authentication",
"redirect": "/docs/products/auth"
},
{
"link": "/docs/authentication-email-pass",
"redirect": "/docs/products/auth/email-password"
},
{
"link": "/docs/authentication-sms",
"redirect": "/docs/products/auth/phone-sms"
},
{
"link": "/docs/authentication-magic",
"redirect": "/docs/products/auth/magic-url"
},
{
"link": "/docs/authentication-oauth",
"redirect": "/docs/products/auth/oauth2"
},
{
"link": "/docs/authentication-anonymous",
"redirect": "/docs/products/auth/anonymous"
},
{
"link": "/docs/authentication-management",
"redirect": "/docs/products/auth/users"
},
{
"link": "/docs/authentication-server",
"redirect": "/docs/authentication-server"
},
{
"link": "/docs/authentication-security",
"redirect": "/docs/products/auth/security"
},
{
"link": "/docs/functions-develop",
"redirect": "/docs/products/functions/development"
},
{
"link": "/docs/functions-deploy",
"redirect": "/docs/products/functions/deployment"
},
{
"link": "/docs/functions-execute",
"redirect": "/docs/products/functions/execution"
},
{
"link": "/docs/functions-runtimes",
"redirect": "/docs/products/functions/runtimes"
},
{
"link": "/docs/functions-examples",
"redirect": "/docs/products/functions/examples"
},
{
"link": "/docs/migrations",
"redirect": "/docs/advanced/migrations"
},
{
"link": "/docs/migrations-firebase",
"redirect": "/docs/advanced/migrations/firebase"
},
{
"link": "/docs/migrations-supabase",
"redirect": "/docs/advanced/migrations/supabase"
},
{
"link": "/docs/migrations-nhost",
"redirect": "/docs/advanced/migrations/nhost"
},
{
"link": "/docs/migrations-cloud-to-self-hosted",
"redirect": "/docs/advanced/migrations/self-hosted"
},
{
"link": "/docs/migrations-self-hosted-to-cloud",
"redirect": "/docs/advanced/migrations/cloud"
},
{
"link": "/docs/keys",
"redirect": "/docs/advanced/platform/api-keys"
},
{
"link": "/docs/permissions",
"redirect": "/docs/advanced/platform/permissions"
},
{
"link": "/docs/events",
"redirect": "/docs/advanced/platform/events"
},
{
"link": "/docs/queries",
"redirect": "/docs/products/databases/queries"
},
{
"link": "/docs/pagination",
"redirect": "/docs/products/databases/pagination"
},
{
"link": "/docs/webhooks",
"redirect": "/docs/advanced/platform/webhooks"
},
{
"link": "/docs/custom-domains",
"redirect": "/docs/advanced/platform/custom-domains"
},
{
"link": "/docs/email-and-sms-templates",
"redirect": "/docs/advanced/platform/message-templates"
},
{
"link": "/docs/response-codes",
"redirect": "/docs/advanced/platform/response-codes"
},
{
"link": "/docs/rate-limits",
"redirect": "/docs/advanced/platform/rate-limits"
},
{
"link": "/docs/configuration",
"redirect": "/docs/advanced/self-hosting"
},
{
"link": "/docs/environment-variables",
"redirect": "/docs/advanced/self-hosting/environment-variables"
},
{
"link": "/docs/email-delivery",
"redirect": "/docs/advanced/self-hosting/email"
},
{
"link": "/docs/sms-delivery",
"redirect": "/docs/advanced/self-hosting/sms"
},
{
"link": "/docs/certificates",
"redirect": "/docs/advanced/self-hosting/tls-certificates"
},
{
"link": "/docs/debugging",
"redirect": "/docs/advanced/self-hosting/debugging"
},
{
"link": "/docs/upgrade",
"redirect": "/docs/advanced/self-hosting/update"
},
{
"link": "/docs/production",
"redirect": "/docs/advanced/self-hosting/production"
},
{
"link": "/docs/server/databases",
"redirect": "/docs/references/cloud/server-nodejs/databases"
},
{
"link": "/docs/client/databases?sdk=web-default",
"redirect": "/docs/references/cloud/client-web/databases?sdk=web-default"
},
{
"link": "/docs/models/document",
"redirect": "/docs/references/cloud/models/document"
},
{
"link": "/docs/models/documentList",
"redirect": "/docs/references/cloud/models/documentList"
},
{
"link": "/docs/server/account",
"redirect": "/docs/references/cloud/server-nodejs/account"
},
{
"link": "/docs/client/account?sdk=web-default",
"redirect": "/docs/references/cloud/client-web/account?sdk=web-default"
},
{
"link": "/docs/models/user",
"redirect": "/docs/references/cloud/models/user"
},
{
"link": "/docs/models/session",
"redirect": "/docs/references/cloud/models/session"
},
{
"link": "/docs/models/identityList",
"redirect": "/docs/references/cloud/models/identityList"
},
{
"link": "/docs/models/token",
"redirect": "/docs/references/cloud/models/token"
},
{
"link": "/docs/models/jwt",
"redirect": "/docs/references/cloud/models/jwt"
},
{
"link": "/docs/models/preferences",
"redirect": "/docs/references/cloud/models/preferences"
},
{
"link": "/docs/models/sessionList",
"redirect": "/docs/references/cloud/models/sessionList"
},
{
"link": "/docs/models/logList",
"redirect": "/docs/references/cloud/models/logList"
},
{
"link": "/docs/server/storage",
"redirect": "/docs/references/cloud/server-nodejs/storage"
},
{
"link": "/docs/client/storage?sdk=web-default",
"redirect": "/docs/references/cloud/client-web/storage?sdk=web-default"
},
{
"link": "/docs/models/file",
"redirect": "/docs/references/cloud/models/file"
},
{
"link": "/docs/models/fileList",
"redirect": "/docs/references/cloud/models/fileList"
},
{
"link": "/docs/models/attributeList",
"redirect": "/docs/references/cloud/models/attributeList"
},
{
"link": "/docs/models/indexList",
"redirect": "/docs/references/cloud/models/indexList"
},
{
"link": "/docs/server/functions",
"redirect": "/docs/references/cloud/server-nodejs/functions"
},
{
"link": "/docs/server/users?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/users?sdk=nodejs-default"
},
{
"link": "/docs/models/userList",
"redirect": "/docs/references/cloud/models/userList"
},
{
"link": "/docs/models/membershipList",
"redirect": "/docs/references/cloud/models/membershipList"
},
{
"link": "/docs/server/teams",
"redirect": "/docs/references/cloud/server-nodejs/teams"
},
{
"link": "/docs/client/teams?sdk=web-default",
"redirect": "/docs/references/cloud/client-web/teams?sdk=web-default"
},
{
"link": "/docs/models/team",
"redirect": "/docs/references/cloud/models/team"
},
{
"link": "/docs/models/teamList",
"redirect": "/docs/references/cloud/models/teamList"
},
{
"link": "/docs/models/membership",
"redirect": "/docs/references/cloud/models/membership"
},
{
"link": "/docs/client/functions?sdk=web-default",
"redirect": "/docs/references/cloud/client-web/functions?sdk=web-default"
},
{
"link": "/docs/models/execution",
"redirect": "/docs/references/cloud/models/execution"
},
{
"link": "/docs/models/executionList",
"redirect": "/docs/references/cloud/models/executionList"
},
{
"link": "/docs/server/locale",
"redirect": "/docs/references/cloud/server-nodejs/locale"
},
{
"link": "/docs/client/locale?sdk=web-default",
"redirect": "/docs/references/cloud/client-web/locale?sdk=web-default"
},
{
"link": "/docs/models/locale",
"redirect": "/docs/references/cloud/models/locale"
},
{
"link": "/docs/models/localeCodeList",
"redirect": "/docs/references/cloud/models/localeCodeList"
},
{
"link": "/docs/models/countryList",
"redirect": "/docs/references/cloud/models/countryList"
},
{
"link": "/docs/models/phoneList",
"redirect": "/docs/references/cloud/models/phoneList"
},
{
"link": "/docs/models/continentList",
"redirect": "/docs/references/cloud/models/continentList"
},
{
"link": "/docs/models/currencyList",
"redirect": "/docs/references/cloud/models/currencyList"
},
{
"link": "/docs/models/languageList",
"redirect": "/docs/references/cloud/models/languageList"
},
{
"link": "/docs/server/avatars",
"redirect": "/docs/references/cloud/server-nodejs/avatars"
},
{
"link": "/docs/client/avatars?sdk=web-default",
"redirect": "/docs/references/cloud/client-web/avatars?sdk=web-default"
},
{
"link": "/docs/permissions/",
"redirect": "/docs/advanced/platform/permissions"
},
{
"link": "/docs/",
"redirect": "/docs/"
},
{
"link": "/docs/models/bucket",
"redirect": "/docs/references/cloud/models/bucket"
},
{
"link": "/docs/models/database",
"redirect": "/docs/references/cloud/models/database"
},
{
"link": "/docs/models/collection",
"redirect": "/docs/references/cloud/models/collection"
},
{
"link": "/docs/models/attribute",
"redirect": "/docs/references/cloud/models/attribute"
},
{
"link": "/docs/models/index",
"redirect": "/docs/references/cloud/models/index"
},
{
"link": "/docs/models/function",
"redirect": "/docs/references/cloud/models/function"
},
{
"link": "/docs/models/deployment",
"redirect": "/docs/references/cloud/models/deployment"
},
{
"link": "/docs/server/databases?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/databases?sdk=nodejs-default"
},
{
"link": "/docs/models/databaseList",
"redirect": "/docs/references/cloud/models/databaseList"
},
{
"link": "/docs/models/collectionList",
"redirect": "/docs/references/cloud/models/collectionList"
},
{
"link": "/docs/models/attributeString",
"redirect": "/docs/references/cloud/models/attributeString"
},
{
"link": "/docs/models/attributeEmail",
"redirect": "/docs/references/cloud/models/attributeEmail"
},
{
"link": "/docs/models/attributeEnum",
"redirect": "/docs/references/cloud/models/attributeEnum"
},
{
"link": "/docs/models/attributeIp",
"redirect": "/docs/references/cloud/models/attributeIp"
},
{
"link": "/docs/models/attributeUrl",
"redirect": "/docs/references/cloud/models/attributeUrl"
},
{
"link": "/docs/models/attributeInteger",
"redirect": "/docs/references/cloud/models/attributeInteger"
},
{
"link": "/docs/models/attributeFloat",
"redirect": "/docs/references/cloud/models/attributeFloat"
},
{
"link": "/docs/models/attributeBoolean",
"redirect": "/docs/references/cloud/models/attributeBoolean"
},
{
"link": "/docs/models/attributeDatetime",
"redirect": "/docs/references/cloud/models/attributeDatetime"
},
{
"link": "/docs/models/attributeRelationship",
"redirect": "/docs/references/cloud/models/attributeRelationship"
},
{
"link": "/docs/server/account?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/account?sdk=nodejs-default"
},
{
"link": "/docs/models/algoArgon2",
"redirect": "/docs/references/cloud/models/algoArgon2"
},
{
"link": "/docs/models/algoScrypt",
"redirect": "/docs/references/cloud/models/algoScrypt"
},
{
"link": "/docs/models/algoScryptModified",
"redirect": "/docs/references/cloud/models/algoScryptModified"
},
{
"link": "/docs/models/algoBcrypt",
"redirect": "/docs/references/cloud/models/algoBcrypt"
},
{
"link": "/docs/models/algoPhpass",
"redirect": "/docs/references/cloud/models/algoPhpass"
},
{
"link": "/docs/models/algoSha",
"redirect": "/docs/references/cloud/models/algoSha"
},
{
"link": "/docs/models/algoMd5",
"redirect": "/docs/references/cloud/models/algoMd5"
},
{
"link": "/docs/models/identity",
"redirect": "/docs/references/cloud/models/identity"
},
{
"link": "/docs/models/log",
"redirect": "/docs/references/cloud/models/log"
},
{
"link": "/docs/server/storage?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/storage?sdk=nodejs-default"
},
{
"link": "/docs/models/bucketList",
"redirect": "/docs/references/cloud/models/bucketList"
},
{
"link": "/docs/server/functions?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/functions?sdk=nodejs-default"
},
{
"link": "/docs/models/functionList",
"redirect": "/docs/references/cloud/models/functionList"
},
{
"link": "/docs/models/runtimeList",
"redirect": "/docs/references/cloud/models/runtimeList"
},
{
"link": "/docs/models/deploymentList",
"redirect": "/docs/references/cloud/models/deploymentList"
},
{
"link": "/docs/models/variable",
"redirect": "/docs/references/cloud/models/variable"
},
{
"link": "/docs/models/variableList",
"redirect": "/docs/references/cloud/models/variableList"
},
{
"link": "/docs/server/teams?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/teams?sdk=nodejs-default"
},
{
"link": "/docs/models/headers",
"redirect": "/docs/references/cloud/models/headers"
},
{
"link": "/docs/server/locale?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/locale?sdk=nodejs-default"
},
{
"link": "/docs/models/localeCode",
"redirect": "/docs/references/cloud/models/localeCode"
},
{
"link": "/docs/models/country",
"redirect": "/docs/references/cloud/models/country"
},
{
"link": "/docs/models/phone",
"redirect": "/docs/references/cloud/models/phone"
},
{
"link": "/docs/models/continent",
"redirect": "/docs/references/cloud/models/continent"
},
{
"link": "/docs/models/currency",
"redirect": "/docs/references/cloud/models/currency"
},
{
"link": "/docs/models/language",
"redirect": "/docs/references/cloud/models/language"
},
{
"link": "/docs/server/avatars?sdk=nodejs-default",
"redirect": "/docs/references/cloud/server-nodejs/avatars?sdk=nodejs-default"
},
{
"link": "/docs/models/runtime",
"redirect": "/docs/references/cloud/models/runtime"
}
]

18
src/hooks/server.ts Normal file
View File

@@ -0,0 +1,18 @@
import type { Handle } from '@sveltejs/kit';
import redirects from './redirects.json';
const redirectMap = new Map(redirects.map(({ link, redirect }) => [link, redirect]));
export const handle: Handle = async ({ event, resolve }) => {
const currentPath = event.url.pathname;
if (redirectMap.has(currentPath)) {
return new Response(null, {
status: 308,
headers: {
location: redirectMap.get(currentPath) ?? ''
}
});
}
return await resolve(event);
};

View File

@@ -112,7 +112,7 @@
</li>
<li class="aw-footer-nav-main-item">
<h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">Learn</h5>
<button class="aw-footer-nav-button is-open aw-is-only-mobile">
<button class="aw-footer-nav-button aw-is-only-mobile" use:accordion>
<span class="aw-caption-500 aw-eyebrow">Learn</span>
<svg
class="aw-footer-nav-button-arrow"
@@ -143,7 +143,7 @@
</li>
<li class="aw-footer-nav-main-item">
<h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">About</h5>
<button class="aw-footer-nav-button is-open aw-is-only-mobile" use:accordion>
<button class="aw-footer-nav-button aw-is-only-mobile" use:accordion>
<span class="aw-caption-500 aw-eyebrow">About</span>
<svg
class="aw-footer-nav-button-arrow"

View File

@@ -33,7 +33,7 @@
<div class="info aw-caption-500" />
</div>
<p class="aw-strip-plans-info aw-caption-500">
For personal passion projects and students.
For students and hobby projects.
</p>
<a href="https://cloud.appwrite.io/register" class="aw-button is-full-width-mobile aw-u-cross-child-end">
<span class="text">Get Started</span>

View File

@@ -1,21 +1,16 @@
<script lang="ts">
import { capitalize } from '$lib/utils/capitalize.js';
import { currentTheme, setTheme, type Theme } from '$routes/+layout.svelte';
import { createSelect, melt } from '@melt-ui/svelte';
import { onMount } from 'svelte';
import { fly } from 'svelte/transition';
const iconMap = {
const iconMap: Record<Theme, string> = {
dark: 'aw-icon-dark',
light: 'aw-icon-light',
system: 'icon-server'
} as const;
};
const themes = ['dark', 'light', 'system'] as const;
type Theme = (typeof themes)[number];
function isTheme(theme: unknown): theme is Theme {
return themes.includes(theme as Theme);
}
const themes: Array<Theme> = ['dark', 'light', 'system'];
const {
elements: { trigger, menu, option },
@@ -23,8 +18,8 @@
} = createSelect<Theme>({
preventScroll: false,
defaultSelected: {
value: 'dark',
label: 'Dark'
value: $currentTheme,
label: capitalize($currentTheme)
},
positioning: {
sameWidth: true,
@@ -33,44 +28,13 @@
forceVisible: true,
onSelectedChange({ curr, next }) {
const t = next?.value;
if (isTheme(t) && t !== curr?.value) {
if (t && t !== curr?.value) {
setTheme(t);
}
open.set(false);
return next;
}
});
function setSelected(theme: Theme) {
selected.set({
value: theme,
label: capitalize(theme)
});
}
function setTheme(theme: Theme) {
document.body.classList.remove('theme-dark', 'theme-light');
if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
document.body.classList.add(`theme-${systemTheme}`);
} else {
document.body.classList.add(`theme-${theme}`);
}
localStorage.setItem('theme', theme);
}
onMount(() => {
const theme = localStorage.getItem('theme');
if (isTheme(theme)) {
setTheme(theme);
setSelected(theme);
} else {
setTheme('dark');
setSelected('dark');
}
});
</script>
<button class="aw-select is-colored" use:melt={$trigger}>

View File

@@ -90,10 +90,6 @@
label: 'Blog',
href: '/blog'
},
// {
// label: 'Changelog',
// href: '#'
// },
{
label: 'Pricing',
href: '/pricing'

View File

@@ -64,11 +64,11 @@
<!-- Titles -->
<title>{seoTitle}</title>
<meta property="og:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -44,11 +44,11 @@
<!-- Titles -->
<title>{seoTitle}</title>
<meta property="og:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -30,11 +30,11 @@
<!-- Titles -->
<title>{seoTitle}</title>
<meta property="og:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -48,11 +48,11 @@
<!-- Titles -->
<title>{title + BLOG_TITLE_SUFFIX}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={DEFAULT_HOST + cover} />
<meta property="og:image:width" content="1200" />

View File

@@ -59,11 +59,11 @@
<!-- Titles -->
<title>{seoTitle}</title>
<meta property="og:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<meta name="twitter:title" content={seoTitle} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -6,8 +6,15 @@
export let id: string | undefined = undefined;
export let step: number | undefined = undefined;
const tag = `h${level}`;
const tag = `h${level + 1}`;
const ctx = hasContext('headings') ? getContext<LayoutContext>('headings') : undefined;
const classList: Record<typeof level, string> = {
1: 'aw-label',
2: 'aw-description',
3: 'aw-main-body-500',
4: 'aw-sub-body-500'
};
let element: HTMLElement | undefined;
onMount(() => {
@@ -47,13 +54,13 @@
{id}
bind:this={element}
class:aw-snap-location={id}
class="aw-main-body-500 aw-u-color-text-primary"
class="{classList[level]} aw-u-color-text-primary"
>
<slot />
</svelte:element>
</a>
{:else}
<svelte:element this={tag} bind:this={element} class="aw-main-body-500 aw-u-color-text-primary">
<svelte:element this={tag} bind:this={element} class="{classList[level]} aw-u-color-text-primary">
<slot />
</svelte:element>
{/if}

View File

@@ -1,3 +1,42 @@
<script lang="ts" context="module">
export type Theme = 'dark' | 'light' | 'system';
export const currentTheme = writable<Theme>(getPreferredTheme());
function isTheme(theme: unknown): theme is Theme {
return ['dark', 'light', 'system'].includes(theme as Theme);
}
function getSystemTheme(): Theme {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
function getPreferredTheme() {
if (!browser) {
return 'dark';
}
const theme = globalThis?.localStorage.getItem('theme');
if (!isTheme(theme)) {
return 'dark';
}
if (theme === 'system') {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
return theme;
}
export function setTheme(theme: string) {
if (!isTheme(theme)) {
return;
}
currentTheme.set(theme === 'system' ? getSystemTheme() : theme);
globalThis?.localStorage.setItem('theme', theme);
}
</script>
<script lang="ts">
import '@fontsource/inter/100.css';
import '@fontsource/inter/200.css';
@@ -9,7 +48,40 @@
import '@fontsource/inter/800.css';
import '@fontsource/inter/900.css';
import '$scss/index.scss';
import { dev } from '$app/environment';
import { browser, dev } from '$app/environment';
import { writable } from 'svelte/store';
import { navigating, page } from '$app/stores';
import { onMount } from 'svelte';
function applyTheme(theme: Omit<Theme, 'system'>) {
const className = `theme-${theme}`;
document.body.classList.add(className);
document.body.classList.remove(`theme-${theme === 'dark' ? 'light' : 'dark'}`);
}
onMount(() => {
const initialTheme = $page.route.id?.startsWith('/docs') ? getPreferredTheme() : 'dark';
applyTheme(initialTheme);
navigating.subscribe((n) => {
if (!n?.to) {
return;
}
const isDocs = n.to.route.id?.startsWith('/docs');
if (isDocs) {
if (!document.body.classList.contains(`theme-${$currentTheme}`)) {
applyTheme($currentTheme);
}
} else {
applyTheme('dark');
}
});
});
$: browser && currentTheme.subscribe((theme) => applyTheme(theme));
</script>
<svelte:head>

View File

@@ -72,11 +72,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -14,11 +14,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -17,11 +17,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -20,7 +20,7 @@ To ensure our products will maintain a high accessibility level, we did the foll
- Define font size in REM
- Allow users to reduce motion
## Use high color contrast
# Use high color contrast
Color contrast might be the first thing that comes to mind when thinking about accessibility. A lack of contrast between the text and background might mean some people would be unable or have difficulty reading the text. Similarly, bright colors with high luminance are not readable for others. W3C recommends a contrast ratio between text and background of 4.5 to 1 for conformance level AA.
@@ -29,7 +29,7 @@ Color contrast might be the first thing that comes to mind when thinking about a
| Apples | 1.99 | *7* |
| Bananas | **1.89** | 5234 |
## Not relying on color
# Not relying on color
The term “color blindness” is often used to describe people who have trouble identifying and distinguishing between certain colors, but color blindness, the inability to see any color, is extremely rare. According to the United Kingdom National Health Service (NHS), red-green color blindness affects 1 out of 12 men and 1 out of 200 women. People with this color vision deficiency may have difficulty differentiating between reds, oranges, yellows, browns, and greens. They also might find it hard to distinguish between shades of purple and may confuse red with black.Similarly, people with “blue-yellow” color vision deficiency may have difficulty differentiating between blues, greens, and yellows.
@@ -38,7 +38,7 @@ We use four system colors in Pink Design — red, orange, green, and blue. Each
>“Lorem ipsum dolor sit amet consectetur. Diam fermentum tellus ante purus nullam eget sit id ac. Purus viverra ultrices fusce posuere sed enim duis aliquam sit. Vitae fames potenti donec ultricies in. Quis sed iaculis consectetur cras feugiat nibh gravida tincidunt volutpat. Eleifend vel blandit cras tempor sed nam quis aliquet. Facilisi tempor amet id integer gravida duis. Aliquet nulla tellus risus tortor neque vestibulum arcu.” Author
## Allow keyboard navigation
# Allow keyboard navigation
People with fine motor control restrictions or disabled hands or arms will be unable to use a mouse. In Pink Design, we provide distinct states for interactive elements. By designing states like focus, hover, and active, we provide the ability to navigate all interactive elements with a keyboard. This is not only an accessible experience but also a better experience for all users who prefer keyboard navigation, including Appwrite's developer community.
@@ -46,7 +46,7 @@ It is possible to enhance accessibility through development as well. In collabor
![Alt text](/images/pages/homepage/dashboard.png "a title")
## Define font size in REM
# Define font size in REM
Browsers have a default font size that users can change via the browser setting. A pixel is an absolute unit for fixed sizes and spaces that ignores browser settings. This means that if we are using pixels and a user (with or without vision impairment) changes the font size in their browser settings, their setting won't affect our product. That being said, pixels should not cause any problems if the user zooms in, but we make no assumptions about users' preferences. This is why we decided to define the font size in REM, which is a relative unit.
@@ -69,7 +69,7 @@ promise.then(function (response) {
```
## Allow users to reduce motion
# Allow users to reduce motion
There is no doubt that animations are a nice addition to every product, but animations can also distract people. In some cases, animations can cause dizziness, vertigo, or epileptic seizures. Users that are sensitive to motion might choose to reduce motion in their operating system settings. In this case, we should skip the animation for them. In Pink Design, we decided to create a big animation to show the functionality of the library on the landing page. The animation is 10 seconds long and is the first thing you see on the page. It starts immediately when the page is loaded, but if “reduce motion” is enabled in the operating system, the animation skips to the end.

View File

@@ -13,11 +13,11 @@ An important day has come for Appwrite, where we finally announce the pricing fo
Now let's dive in.
## Building for the future
# Building for the future
As part of our mission to make software more accessible, we wanted to make sure our pricing compliments that mission but also enable us to have the resources to continue building a strong company that can reach new levels. We have put a lot of effort into creating Appwrite's pricing that aligns with our values, transparency, ambition, and simplicity.
## Value framework
# Value framework
We created a set of principles to guide us through the pricing process. We like to call this the “Value Framework” as it focuses on delivering the maximum value to our users without compromising on the affordability and accessibility of our products and services.
@@ -28,11 +28,11 @@ We created a set of principles to guide us through the pricing process. We like
- Focus on value based profit. Limits should generally be applied to usage. Not functionality.
- Be fair.
## Affordable and accessible
# Affordable and accessible
The above framework supports our goal to make Appwrite Cloud affordable and accessible to as many developers as possible. We worked together with developers in the Appwrite community to create a transparent and predictable pricing model. We took insights from current costs made, interviews, surveys, as well as pricing of similar products as a baseline to work towards a fair model. A model where costs should never get in the way of your ambitions, the costs are always transparent, and it is as simple for you to get started as it is to stop. With all this in mind, we believe we will build a strong trust with the Appwrite community, which will eventually lead to Appwrite's growth.
## Pricing plans
# Pricing plans
![Appwrite pricing plans](/images/blog/pricing-plans.png)
@@ -45,17 +45,17 @@ $15, per month, per member
**Scale plan** a plan that offers more support as you continue to scale your commercial product and team. With higher limits and more support from our team to ensure we support the demand of scaling teams.
$685, per month, per organization
## Business model: Pay per organization member
# Business model: Pay per organization member
We chose a model that differs from most in the industry, a business model that focuses on you as a developer instead of a plan around the number of projects you build. We see value in unlimited building, we see value in exploration and in learning. We never want to get in the way of your imagination or ideation.
Our business model is designed to support developers with a lot of freedom to build and explore, as well as to scale. We've designed our pricing model to reflect a shared journey of growth and success. As your organization flourishes and expands, welcoming new team members, our pricing plan mirrors this journey. Instead of viewing it as a simple fee per new member, think of it as a tangible marker of your organization's progress and evolution. Each addition to your team is a sign of your success and, in turn, contributes to our shared advancement. In this way, we evolve together in a business model that's designed to be as fair and as reflective of our collective growth. We believe in growing together because your success is our success.
## Our commitment to the open source community
# Our commitment to the open source community
One thing we cannot dismiss is our OSS program. We strongly believe in helping other Open Source (OSS) maintainers. We know very well where we came from and Appwrite has been built with and by the open-source community. Therefore we have a free program to support the OSS community and show our appreciation. Interested developers can apply on our website once pricing is available.
## Next steps
# Next steps
This is a big step forward for Appwrite and the community and we are excited to see the response to our plans. The coming weeks we will work hard on making our pricing available, but until then developers can continue to build on Appwrite free of charge.
- [Review the pricing comparsion](/pricing)

View File

@@ -16,7 +16,7 @@ Today, we took another big step in improving this experience by elevating the Ap
We are excited to share our new brand and to see it match the maturity of our products, services, and content. And how, together, and through the power of open source, we have the capabilities of hundreds of developers.
## Aligning visual identity with growth
# Aligning visual identity with growth
The very first design of Appwrite was created by our Founder & CEO, Eldad, in 2019 when Appwrite launched as an open-source project. Since then, the Appwrite Console has been through a design upgrade, but as Appwrite grew, so did the team. Making it possible to reach new heights with Appwrites overall brand identity.
@@ -24,7 +24,7 @@ The very first design of Appwrite was created by our Founder & CEO, Eldad, in 20
With the Appwrite team and community growing, our product started to mature, and there was a disconnect between our broader visual identity and our product. Recognizing the need for a fresh and more mature appearance, we worked to align our visual identity with the growing maturity of our product. This rebranding effort represents our commitment to delivering a polished and sophisticated experience to developers, throughout the developer journey. From discovery to scaling in using Appwrite.
## Designed for the community
# Designed for the community
Our rebranding journey began with a fresh perspective on our logo. We wanted to emphasize the importance of the Appwrite community, so we redesigned it to feature a globe and lines of code. This represents our global community members, working and coding together to form the letter 'a,' for Appwrite.
@@ -40,7 +40,7 @@ Additionally, we've added a new element: glass. This represents our commitment t
![Appwrite's glass elements](/images/blog/glass-elements.png)
## Introducing our enhanced website and docs
# Introducing our enhanced website and docs
Our upgraded website is the main product of our new brand bringing more pages explaining everything you need to know about Appwrite. We have more webpages to come explaining our products and features in more depth.
@@ -48,6 +48,6 @@ Our upgraded website is the main product of our new brand bringing more pages ex
As part of our rebranding effort, we've revamped not only our website but also our documentation. Recognizing that our documentation plays a pivotal role in a developer's workflow, we've invested in enhancing both its design and content. Our new documentation now features specialized tutorials to guide you through project setup and feature implementation step by step.
## Build like a team of 100
# Build like a team of 100
With open source at the heart of everything we do, community plays an important role at Appwrite. We believe that if we stay true to our philosophy, together, we will empower developers with the capabilities of hundreds of developers. Giving them the freedom to build, create, and innovate.

View File

@@ -15,47 +15,47 @@ We're thrilled to announce a major step forward for Appwrite Cloud as we transit
**TL;DR Sign up at [cloud.appwrite.io/register](https://cloud.appwrite.io/register)**
## Why Appwrite Cloud?
# Why Appwrite Cloud?
At Appwrite, we are committed to the open-source community and believe that developers should have access to powerful tools and services that are intuitive, developer-centric and affordable. With Appwrite Cloud, we are extending our commitment to provide developers with the best possible experience by offering a fully managed backend solution that simplifies infrastructure management and helps them focus on what they do best - building great applications!
## What was the private beta?
# What was the private beta?
Over the last couple of months, we conducted a successful private beta that allowed us to get Appwrite Cloud in the hands of selected members of the community. This exercise allowed us to learn a lot about usage patterns, infrastructure performance, early feedback and lots more.
We conducted cloud interviews with members of the initial cohort to understand their use cases and identify the most important features for them. These conversations have been invaluable in shaping the direction of Appwrite Cloud, allowing us to prioritize features and improvements.
We also conducted a pricing survey with participants to better understand developer demographics, their needs, their budgets and expectations. This information was instrumental in helping us fine-tune our pricing strategy and deliver the best value for our developers.
## What's new in the public beta?
# What's new in the public beta?
With the launch of the public beta, we're opening up access to the Appwrite Cloud to a broader audience, allowing more developers to explore and test our platform. The public beta retains all the features and benefits of the private beta while incorporating valuable feedback from our early adopters.
Additionally, we'll continue working closely with the Appwrite community to refine the platform and introduce new features based on user feedback. We also encourage you to join our Discord community where you can get help with anything Appwrite related!
## Whats next?
# Whats next?
We have a lot of things planned in the upcoming months while we await Cloud to become publicly available, and wed love to share some highlights with you.
### Cloud interviews and surveys
## Cloud interviews and surveys
Were conducting a series of interviews & surveys with participants of the Public Beta to get more insights into their requirements. During these interviews, we focus on understanding their background, their reasons for using a backend server like Appwrite, their use cases, their experience so far, along with their expectations and shortcomings of the platform. These interviews have provided key insights that have prompted us to steer in the right direction.
If youre part of the Beta and would like to participate in these interviews, please reach out to me on the Appwrite Discord or my email, and wed be glad to set up a call.
### Pricing
## Pricing
Our goal is to make Appwrite Cloud affordable and accessible to all developers. Weve had some really great feedback from our initial pricing survey and are really close to sharing our model with you all. We will continue working together with the Appwrite community to refine this pricing model. Rest assured, there will be a generous free tier for all the hobby projects youve been wanting to create!
### Self-hosted edition
## Self-hosted edition
A lot of us may have questions about the open source version of Appwrite and its future. We can proudly say, we will continue to stand among the handful of companies that have been open-source first. Our vibrant community is a testament that, for the longest time, we have prioritized the open source version, and we will continue to do so. In fact, all major features will roll out to the open source version even before they hit the cloud! Appwrite will forever remain open source!
### Multi-region support
## Multi-region support
During the Beta, were operating with Frankfurt as our primary region. This is a careful decision to ensure we are geographically centrally located. As we get closer to general availability, we will focus on 3 more regions, namely San Francisco, New York, and Singapore with more regions to follow.
### Compliance
## Compliance
Compliances are frameworks that help organizations ensure they are meeting certain standards and requirements in regard to data security and privacy. For most SaaS/BaaS companies, SOC 2, HIPAA & GDPR are the essential ones. These certifications help companies demonstrate to their customers and stakeholders they are taking data security and privacy seriously, and are committed to protecting their sensitive information.
These usually involve a lot of paperwork, documentation, and administrative processes. Were in the process of ensuring we meet the highest standards for data security and privacy.
### Support for more function runtimes
## Support for more function runtimes
While in beta, Appwrite Cloud supports five serverless runtimes, namely, Node, Python, PHP, Ruby, and Dart. As we approach general availability, we will continue to add support for our entire suite of runtimes based on the requests and requirements of the beta participants.
## Coming up
# Coming up
Weve set multiple goals and key performance indicators to help us determine the success of this important stage before making the Appwrite Cloud generally available. Those indicators include the feedback and insights we get from beta participants, consumption metrics, and our infrastructure resilience during this time. Once those are achieved, we'll officially announce the release of the Appwrite Cloud platform and reach general availability.
As always, huge thanks to the Appwrite community for your unwavering support. This milestone would not have been possible without your contributions. You're all incredible, and we'll continue working hard to deliver the development platform you deserve.

View File

@@ -16,11 +16,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -14,11 +14,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -43,11 +43,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -14,11 +14,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -17,11 +17,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -8,7 +8,7 @@ readtime: 5
If you're looking to migrate existing projects to Appwrite, Migrations can help you make the move more quickly. You can move your app from Firebase, Supabase, Nhost, and even move between self-hosted and Cloud projects using Migrations. You can also use Migrations to move between two self-hosted instances or even to duplicate projects on the same instance. Migrations will automatically move accounts, database documents, and storage files from one source to another.
## Sources {% #sources %}
# Sources {% #sources %}
Appwrite supports multiple source destinations for migrating your data. You can transfer data from these sources to a new or existing Appwrite project. Resources marked as 'enabled' are migrated automatically. Resources marked as 'partial' can be migrated but with limitations or caveats; please refer to the guide for each source to learn more. Resources marked as 'manual' require manual migration.
@@ -20,7 +20,7 @@ Appwrite supports multiple source destinations for migrating your data. You can
| [Cloud](/docs/advanced/migrations/cloud) | enabled | enabled | enabled | enabled | enabled |
| [Self hosted](/docs/advanced/migrations/self-hosted) | enabled | enabled | enabled | enabled | enabled |
## Limitations {% #limitations %}
# Limitations {% #limitations %}
Migrations cannot transfer all data perfectly, so certain fields, such as `$createdAt` and `$updatedAt`, may not be transferred.
More information can be found on the migration page for each source.
@@ -28,6 +28,6 @@ More information can be found on the migration page for each source.
Migrations help you jump-start your move, but because each product is unique, complex databases and product unique features like functions might need to be migrated manually.
We also recommend you carefully **validate permissions and data integrity** when moving between platforms.
## Charges {% #charges %}
# Charges {% #charges %}
When you migrate data from another source to Appwrite Cloud, the resource usage during the migration will not count towards your Appwrite Cloud usage charges. However, your source vendor may have data transfer charges. The same is true for moving data between self-hosted Appwrite instances hosted on different cloud providers.

View File

@@ -64,7 +64,7 @@ To begin migrating to Appwrite, follow these steps.
{% /section %}
## Limitations {% #limitations %}
# Limitations {% #limitations %}
Not all vendors make their APIs publicly accessible or easy to use for extracting and fully owning your data. Furthermore, due to varying design philosophies, certain resources cannot be migrated on a one-to-one basis. Below, you'll find a list of some known limitations when migrating data from Firebase to Appwrite. It's advisable to review this list before initiating your migration or deploying your product in a production environment.

View File

@@ -51,7 +51,7 @@ Before migrating to Appwrite make sure you've read the [migration overview](/doc
{% /section %}
## Limitations {% #limitations %}
# Limitations {% #limitations %}
Not all vendors make their APIs publicly accessible or easy to use for extracting and fully owning your data. Furthermore, due to varying design philosophies, certain resources cannot be migrated on a one-to-one basis. Below, you'll find a list of some known limitations when migrating data from Nhost to Appwrite. It's advisable to review this list before initiating your migration or deploying your product in a production environment.

View File

@@ -53,7 +53,7 @@ Before migrating to Appwrite make sure you've read the [migration overview](/doc
{% /section %}
## Limitations {% #limitations %}
# Limitations {% #limitations %}
Not all vendors make their APIs publicly accessible or easy to use for extracting and fully owning your data. Furthermore, due to varying design philosophies, certain resources cannot be migrated on a one-to-one basis. Below, you'll find a list of some known limitations when migrating data from Supabase to Appwrite. It's advisable to review this list before initiating your migration or deploying your product in a production environment.

View File

@@ -12,7 +12,7 @@ It is a best practice to grant only the scopes you need to meet your project's g
API keys should be treated as a secret. Never share the API key and keep API keys out of client applications.
{% /info %}
## Create API key {% #create-api-key %}
# Create API key {% #create-api-key %}
{% only_dark %}
![Project settings screen](/images/docs/platform/dark/create-api-key.png)
@@ -26,7 +26,7 @@ To create a new API key, navigate to **Overview** > **Integration** > **API keys
When adding a new API Key, you can choose which [scopes](#scopes) to grant your application.
If you need to replace your API Key, create a new key, update your app credentials and, once ready, delete your old key.
## Scopes {% #scopes %}
# Scopes {% #scopes %}
| Name | Description |
|------------------|-----------------------------------------------------------------------|

View File

@@ -6,7 +6,7 @@ description: Customize your Appwrite platform with custom domains. Learn how to
Appwrite custom domains allows you to use your own domain as your Appwrite API endpoint.
## Third-party cookies {% 3rd-party-cookies %}
# Third-party cookies {% #third-party-cookies %}
A recent change made in modern browsers will not allow your web app to use 3rd-party cookies.
This change is done to protect your users' privacy from malicious web tracking services.
@@ -17,7 +17,7 @@ as a fallback Appwrite will store your users' sessions on the browser localStora
Using localStorage is very convenient to help you get started quickly with Appwrite, but it is not the best practice for your users' security.
The browser localStorage can't protect your users' sessions from being hijacked by a 3rd party script or an XSS vulnerability in your web app.
## Appwrite API endpoint {% endpoint %}
# Appwrite API endpoint {% #endpoint %}
To prevent your browser from blocking your cookies, your Appwrite API endpoint should be set to under same domain of your web app's domain.
When accessing Appwrite from the same domain as the one your app uses,
Appwrite cookies will no longer be treated as 3rd-party cookies by any browser and will store your users' sessions securely.
@@ -26,7 +26,7 @@ For example, if your app runs on [my-app.com](https://my-app.com),
you can set the subdomain [appwrite.my-app.com](https://appwrite.my-app.com) to access the Appwrite API.
This will allow browsers to respect the Appwrite sessions cookies as they are set on the same domain as your app.
## Add a custom domain {% domain %}
# Add a custom domain {% #domain %}
1. Go to the Appwrite Console and navigate to your project.
2. Click on the **Settings** tab in the left sidebar.
@@ -39,7 +39,7 @@ With these steps, your Appwrite project will accept API requests from your custo
If you encounter any issues during the setup process or have questions, don't hesitate to [contact us](/contact-us), and we'll be happy to assist you.
## Add a CNAME record {% #cname-record %}
# Add a CNAME record {% #cname-record %}
A [CNAME record](https://en.wikipedia.org/wiki/CNAME_record) (or a Canonical Name record) is a type of resource record in the Domain Name System (DNS), which maps one domain name (an alias) to another.

View File

@@ -22,7 +22,7 @@ You can find a list of events for Storage, Databases, Functions, and Authenticat
{% partial file="functions-events.md" /%}
## Known limitations {% #known-limitations %}
# Known limitations {% #known-limitations %}
When events fire, only existing subscriptions for that event will receive the update. If your client or server side integrations lose network connection temporarily, delivery of the event is not guaranteed.

View File

@@ -8,7 +8,7 @@ Appwrite uses emails to communicate with users to perform authentication and ver
Each Appwrite project can have its own set of unique templates. Templates also support localization, so every template can be written in multiple languages and served depending on the configured locale.
## Custom SMTP server {% #smtp %}
# Custom SMTP server {% #smtp %}
Appwrite Cloud has a default SMTP server to get you started. This SMTP server sends generic emails and doesn't allow customizing SMTP templates. To use custom SMTP templates, you will need to configure your own SMTP server.
@@ -20,7 +20,7 @@ There are many third-party SMTP providers like SendGrid and Mailgun. Before proc
4. Input **Sender name**, **Sender email**, **Server host**, **Server port**, **Username**, and **Password** from your provider.
5. Click **Update**.
## Customize templates {% #customize %}
# Customize templates {% #customize %}
You can customize email templates for each of your projects in the Appwrite Console.
@@ -35,11 +35,11 @@ Configure a [custom SMTP server](#smtp) to enable custom email templates.
4. Select the **Template language**. You can have a different template for each language your app supports.
5. Update the email template fields and click **Update** to save your changes.
## Email templates {% #email-templates %}
# Email templates {% #email-templates %}
You can customize the email templates for account verification, magic-url authentication, password resets, and user invites.
### Email template components {% #email-template-components %}
## Email template components {% #email-template-components %}
Each email template has the following components that you can customize.
@@ -51,7 +51,7 @@ Each email template has the following components that you can customize.
| Subject | The title of the email. |
| Message | The body of the email in HTML format. You can find the variables available in the [Email Template Syntax](#email-template-syntax) section. |
### Email template syntax {% #email-template-syntax %}
## Email template syntax {% #email-template-syntax %}
Variables can be used in email templates to dynamically construct unique emails for each reader. These variables can only be used in the **Message** field of the email template.
@@ -62,7 +62,7 @@ Variables can be used in email templates to dynamically construct unique emails
| `{{user}}` | The name of the user receiving the email. This variable is not available in the Magic URL template, as there might not be a user yet. |
| `{{redirect}}`| The URL for the user to complete the email template's action. |
### Email template syntax {% #email-template-examples %}
## Email template syntax {% #email-template-examples %}
Here's an example of using these variables in a template.
@@ -113,7 +113,7 @@ Here's an example of using these variables in a template.
</html>
```
## Localization {% #localization %}
# Localization {% #localization %}
Each template can have multiple supported locales, displayed in different format and language. This can be configured under the **Template language** selector of each template.

View File

@@ -14,23 +14,23 @@ All permissions can be granted to individuals or groups of users, entire teams,
A project user can only grant permissions to a resource that they own. For example, if a user is trying to share a document with a team that they are not a member of, they will encounter a 401 not authorized error. If your app needs users to grant access to teams they're not a member of, you can create Appwrite Functions with a [Server SDK](/docs/sdks#server) to achieve this functionality.
## Appwrite resource {% appwrite-resource %}
# Appwrite resource {% #appwrite-resource %}
An Appwrite resource can be a database, collection, document, bucket, or file. Each resource has its own set of permissions to define who can interact with it.
Using the Appwrite permissions mechanism, you can grant resource access to users, teams, and members with different roles.
## Default values {% default-values %}
# Default values {% #default-values %}
If you create a resource using a Server SDK or the Appwrite Console without explicit permissions, no one can access it by default because the permissions will be empty. If you create a resource using a Client SDK without explicit permissions, the creator will be granted read, update, and delete permissions on that resource by default.
## Server integration {% server-integration %}
# Server integration {% #server-integration %}
Server integrations can be used for increased flexibility. When using a Server SDK in combination with the proper [API key scopes](/docs/advanced/platform/api-keys#scopes), you can have any type of access to any of your project resources regardless of their permissions.
Using the server integration flexibility, you can change resource permissions, share resources between different users and teams, or edit and delete them without any limitations.
## Permission types {% permission-types %}
# Permission types {% #permission-types %}
In Client and Server SDKs, you will find a **Permission** class with helper methods for each role described below:
@@ -42,7 +42,7 @@ In Client and Server SDKs, you will find a **Permission** class with helper meth
| `Permission.delete()` | Access to remove a resource. Does not apply to functions. |
| `Permission.write()` | Alias to grant create, update, and delete access for collections and buckets and update and delete access for documents and files. |
## Permission roles {% permission-roles %}
# Permission roles {% #permission-roles %}
In Client and Server SDKs, you will find a **Role** class with helper methods for each role described below:
@@ -57,13 +57,13 @@ In Client and Server SDKs, you will find a **Role** class with helper methods fo
| `Role.member([MEMBERSHIP_ID])` | Grants access to a specific member of a team. When the member is removed from the team, they will no longer have access. |
| `Role.label([LABEL_ID])` | Grants access to all accounts with a specific label ID. Once the label is removed from the user, they will no longer have access. [Learn more about labels](/docs/products/auth/labels). |
## Examples {% examples %}
# Examples {% #examples %}
The examples below will show you how you can use the different Appwrite permissions to manage access control to your project resources.
The following examples are using the [Appwrite Web SDK](https://github.com/appwrite/sdk-for-web) but can be applied similarly to any of the other [Appwrite SDKs](/docs/sdks).
### Example #1 - Basic usage
## Example #1 - Basic usage
In the following example, we are creating a document that can be read by anyone, edited by writers or admins, and deleted by administrators or a user with the user ID `user:5c1f88b42259e`.
@@ -96,7 +96,7 @@ promise.then(function (response) {
});
```
### Example #2 - Team roles {% examples-2 %}
## Example #2 - Team roles {% #examples-2 %}
In the following example, we are creating a document that can be read by members of the team with ID `5c1f88b87435e` and can only be edited or deleted by members of the same team that possess the team role `owner`.

View File

@@ -4,7 +4,7 @@ title: Rate-limits
description: Optimize application performance with Appwrite rate limits. Explore rate limiting strategies, configurations, and how to prevent abuse of your services.
---
## Appwrite rate limits {% appwrite-rate-limits %}
# Appwrite rate limits {% #appwrite-rate-limits %}
Some of Appwrite's API endpoints have a rate limit to avoid abuse or brute-force attacks against Appwrite's REST API. Each Appwrite route documentation has information about any rate limits that might apply to them.
@@ -50,7 +50,7 @@ X-RateLimit-Reset: 1377013266
}
```
## Service abuse {% service-abuse %}
# Service abuse {% #service-abuse %}
To protect the quality of service from Appwrite, additional rate limits may apply to some actions. For example, rapidly creating content, polling aggressively instead of using webhooks, making API calls with a high concurrency, or repeatedly requesting data that is computationally expensive may result in abuse rate limiting.

View File

@@ -10,7 +10,7 @@ Appwrite uses conventional HTTP response codes to indicate the success or failur
- Codes in the `4xx` range indicate an error caused by invalid request, usually caused by user error.
- Codes in the `5xx` range indicate an error with Appwrite, please check Docker container logs.
## Response codes {% #response-codes %}
# Response codes {% #response-codes %}
| Code | Text | Description |
|------|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 200 | OK | Success! |
@@ -32,7 +32,7 @@ Appwrite uses conventional HTTP response codes to indicate the success or failur
| 503 | Service Unavailable | The Appwrite servers are up but overloaded with requests. Try again later. |
| 504 | Gateway timeout | The Appwrite servers are up, but the request couldn't be serviced due to some failure within the stack. Try again later. |
## Error messages {% #error-messages %}
# Error messages {% #error-messages %}
When the Appwrite APIs return error messages, it does so in JSON format. For example, an error might look like this:
@@ -44,7 +44,7 @@ When the Appwrite APIs return error messages, it does so in JSON format. For exa
}
```
## Error types {% #error-types %}
# Error types {% #error-types %}
Appwrite also passes convenient error types in addition to the HTTP response codes to help you get more fine-grained control over what went wrong and allowing you to display relevant error messages in your applications. Error types are convenient to identify the type of error that occurred.

View File

@@ -6,15 +6,15 @@ description: Leverage webhooks in the Appwrite platform for real-time updates. L
Webhooks allow you to build or set up integrations which subscribe to certain events on Appwrite. When one of those events is triggered, we'll send an HTTP POST payload to the webhook's configured URL. Webhooks can be used to purge cache from CDN, calculate data or send a Slack notification. You're only limited by your imagination.
## Add your webhook {% #addWebhook %}
# Add your webhook {% #addWebhook %}
You can set your webhook by adding it from your Appwrite project dashboard. You can access your webhooks settings from your project dashboard or on the left navigation panel. Click the 'Add Webhook' button and choose your webhook name and the events that should trigger it. You can also set an optional basic HTTP authentication username and password to protect your endpoint from unauthorized access.
## Payload {% #payload %}
# Payload {% #payload %}
Each event type has a specific payload format with the relevant event information. All event payloads mirror the payloads for the API payload which parallel to the [event types](/docs/advanced/platform/events).
## Headers {% #headers %}
# Headers {% #headers %}
HTTP requests made to your webhook's configured URL endpoint will contain several special headers.
@@ -28,7 +28,7 @@ HTTP requests made to your webhook's configured URL endpoint will contain severa
| X-Appwrite-Webhook-Signature | The HMAC-SHA1 signature of the payload. This is used to verify the authenticity of the payload. |
| User-Agent | Each request made by Appwrite will be 'Appwrite-Server'. |
## Verification {% #verification %}
# Verification {% #verification %}
Webhooks can be verified by using the [X-Appwrite-Webhook-Signature](/docs/advanced/platform/webhooks#headers) header.
This is the HMAC-SHA1 signature of the payload. You can find the signature key in your webhooks properties in the dashboard.
@@ -37,7 +37,7 @@ After you've generated the signature, compare it to the `X-Appwrite-Webhook-Sign
If they match, the payload is valid and you can trust it came from your Appwrite instance.
## Events {% #events %}
# Events {% #events %}
Appwrite has events that fire when a resource changes.
These events cover all Appwrite resources and can reflect create, update, and delete actions.

View File

@@ -6,7 +6,7 @@ description: Explore advanced self-hosting options with Appwrite. Learn how to g
Appwrite was designed from the ground up with self-hosting in mind. You can install and run Appwrite on any operating system that can run a [Docker CLI](https://www.docker.com/products/docker-desktop). Self-hosted Appwrite instances can be configured flexibly with access to the same features found on Appwrite Cloud.
## System requirements {% #system-requirements %}
# System requirements {% #system-requirements %}
Appwrite is designed to run well on both small and large deployments. The minimum requirements to run Appwrite are as little as **1 CPU core** and **2GB of RAM**, and an operating system that supports Docker.
@@ -16,7 +16,7 @@ Appwrite requires [Docker Compose Version 2](https://docs.docker.com/compose/ins
If you are migrating from an older version of Appwrite, you need to follow the [migration instructions](/docs/advanced/self-hosting/update)
{% /info %}
## Install with Docker {% #install-with-docker %}
# Install with Docker {% #install-with-docker %}
The easiest way to start running your Appwrite server is by running our Docker installer tool from your terminal. Before running the installation command, make sure you have [Docker CLI](https://www.docker.com/products/docker-desktop) installed on your host machine.
@@ -29,7 +29,7 @@ You will be prompted to configure the following during the setup command:
{% tabs %}
{% tabsitem #unix title="macOS and Linux" %}
### Bash
## Bash
```sh
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
@@ -40,7 +40,7 @@ docker run -it --rm \
{% /tabsitem %}
{% tabsitem #windows title="Windows" %}
### CMD
## CMD
```cmd
docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
@@ -48,7 +48,7 @@ docker run -it --rm ^
--entrypoint="install" ^
appwrite/appwrite:1.4.3
```
### Powershell
## Powershell
```powershell
docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock `
@@ -59,7 +59,7 @@ docker run -it --rm `
{% /tabsitem %}
{% /tabs %}
## One-click setups {% #one-click-setups %}
# One-click setups {% #one-click-setups %}
In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running with Appwrite quickly without installing Docker on your local machine.
@@ -71,7 +71,7 @@ Choose from one of the providers below:
{% icon icon="gitpod" /%}| Gitpod | [Click to install](https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod)
{% icon icon="akamai" /%}| Akamai Compute | [Click to install](https://www.linode.com/marketplace/apps/appwrite/appwrite/)
## Next steps {% #next-steps %}
# Next steps {% #next-steps %}
Self-hosting Appwrite gives you more configurable options.
Make these configurations to unlock the full power of Appwrite.
@@ -86,7 +86,7 @@ Make these configurations to unlock the full power of Appwrite.
[Configure TLS Certificates](/docs/advanced/self-hosting/tls-certificates)
## Manual (Docker Compose) {% #manual %}
# Manual (Docker Compose) {% #manual %}
For advanced Docker users, the manual installation might seem more familiar. To set up Appwrite manually, download the Appwrite base `docker-compose.yml` and `.env` files, then move them inside a directory named `appwrite`. After the download completes, update the different environment variables as you wish in the `.env` file and start the Appwrite stack using the following Docker command:
@@ -96,7 +96,7 @@ docker compose up -d --remove-orphans
Once the Docker installation completes, go to your machine's hostname or IP address on your browser to access the Appwrite Console. Please note that on hosts that are not Linux-native, the server might take a few minutes to start after installation completes.
## Stop {% #stop %}
# Stop {% #stop %}
You can stop your Appwrite containers by using the following command executed from the same directory as your `docker-compose.yml` file.
@@ -104,7 +104,7 @@ You can stop your Appwrite containers by using the following command executed fr
docker compose stop
```
## Uninstall {% #uninstall %}
# Uninstall {% #uninstall %}
To stop and remove your Appwrite containers, you can use the following command executed from the same directory as your `docker-compose.yml` file.

View File

@@ -6,7 +6,7 @@ description: Master debugging techniques for self-hosted Appwrite. Discover best
Appwrite comes with a few built-in tools and methods that easily debug and investigate issues on your Appwrite stack environment.
## Doctor CLI {% #doctor-cli %}
# Doctor CLI {% #doctor-cli %}
The doctor CLI helps you validate your server health and best practices. Using the Doctor CLI, you can verify your server configuration for best practices, validate your Appwrite stack connectivity and storage read and write access, and available storage space.
@@ -16,7 +16,7 @@ To run the Doctor check, simply run the following command from your terminal. Yo
docker exec appwrite doctor
```
## Logs {% #logs %}
# Logs {% #logs %}
Checking your Appwrite containers can be a great way to pinpoint where and what exactly happens inside your Appwrite services. You can list your Appwrite containers using the following command in your terminal:
@@ -30,13 +30,13 @@ The output of this command will show you a list of all your running Docker conta
docker logs [CONTAINER-ID]
```
## Status codes {% #status-codes %}
# Status codes {% #status-codes %}
Appwrite uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, invalid input, etc.). Codes in the 5xx range indicate an error with the Appwrite server, but these are rare.
[Learn more about Appwrite status codes {% icon icon="cheveron-right" /%}](/docs/advanced/platform/response-codes)
## Development mode {% #development-mode%}
# Development mode {% #development-mode%}
When moving to dev mode, your server will produce much more verbose error messages. Instead of getting a general 500 error, you'll be able to view the exact error that happened on the server, debug the issue further or [report it to the Appwrite team](https://github.com/appwrite/appwrite/issues/new?body=500%20Error).

View File

@@ -10,7 +10,7 @@ Because email deliverability can be both tricky and hard, it is often easier to
In this document, you will learn how to connect a 3rd party SMTP provider like MailGun or SendGrid with Appwrite to help you get better email deliverability.
## Environment variables {% #environment-variables %}
# Environment variables {% #environment-variables %}
At this stage, we assume that you have already installed Appwrite. If not, you can follow our [Self Hosting Guide](/docs/advanced/self-hosting) for the installation. Appwrite offers multiple environment variables to customize your server setup to your needs. To configure Appwrite to use your own SMTP server, you need to set the following environment variables in the hidden .env file that comes with your Appwrite installation.
@@ -36,7 +36,7 @@ _APP_SYSTEM_EMAIL_ADDRESS=YOUR-SENDER-EMAIL
{% partial file="update-variables.md" /%}
## Debugging {% #debugging %}
# Debugging {% #debugging %}
If you are unable to send emails, there is most likely an issue with your integration. The first place to look for possible errors is the **Appwrite Emails Worker**. You can access the logs of this container using:

View File

@@ -19,7 +19,7 @@ You can verify if the changes have been successfully applied by running this com
docker compose exec appwrite vars
```
## General {% #general %}
# General {% #general %}
| Name | Description |
|------|-------------|
| `_APP_ENV` | Set your server running environment. By default, the var is set to 'development'. When deploying to production, change it to: 'production'. |
@@ -46,7 +46,7 @@ docker compose exec appwrite vars
| `_APP_WORKER_PER_CORE` | **(version >= 0.13.0)** Internal Worker per core for the API, Realtime and Executor containers. Can be configured to optimize performance. |
## Redis {% #redis %}
# Redis {% #redis %}
Appwrite uses a Redis server for managing cache, queues and scheduled tasks. The Redis env vars are used to allow Appwrite server to connect to the Redis container.
| Name | Description |
@@ -69,7 +69,7 @@ Appwrite is using a MariaDB server for managing persistent database data. The Ma
| `_APP_DB_PASS` | MariaDB server user password. Default value is: `password`. |
| `_APP_DB_ROOT_PASS` | MariaDB server root password. Default value is: `rootsecretpassword`. |
## InfluxDB {% #influxdb %}
# InfluxDB {% #influxdb %}
Appwrite uses an InfluxDB server for managing time-series data and server stats. The InfluxDB env vars are used to allow Appwrite server to connect to the InfluxDB container.
| Name | Description |
@@ -78,7 +78,7 @@ Appwrite uses an InfluxDB server for managing time-series data and server stats.
| `_APP_INFLUXDB_PORT` | InfluxDB server TCP port. Default value is: `8086`. |
## StatsD {% #statsd %}
# StatsD {% #statsd %}
Appwrite uses a StatsD server for aggregating and sending stats data over a fast UDP connection. The StatsD env vars are used to allow Appwrite server to connect to the StatsD container.
@@ -88,7 +88,7 @@ Appwrite uses a StatsD server for aggregating and sending stats data over a fast
| `_APP_STATSD_PORT` | StatsD server TCP port. Default value is: `8125`. |
## SMTP {% #smtp %}
# SMTP {% #smtp %}
Appwrite is using an SMTP server for emailing your projects users and server admins. The SMTP env vars are used to allow Appwrite server to connect to the SMTP container.
@@ -103,14 +103,14 @@ If running in production, it might be easier to use a 3rd party SMTP server as i
| `_APP_SMTP_PASSWORD` | SMTP server user password. Empty by default. |
## Phone {% #phone %}
# Phone {% #phone %}
| Name | Description |
|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `_APP_SMS_PROVIDER` | **version >= 0.15.0** Provider used for delivering SMS for Phone authentication. Use the following format: 'sms://[USER]:[SECRET]@[PROVIDER]'.<br>Ensure `[USER]` and `[SECRET]` are URL encoded if they contain any non-alphanumeric characters.<br>Available providers are twilio, text-magic, telesign, msg91, and vonage. |
| `_APP_SMS_FROM` | **version >= 0.15.0** Phone number used for sending out messages. Must start with a leading '+' and maximum of 15 digits without spaces (+123456789). |
## Storage {% #storage %}
# Storage {% #storage %}
| Name | Description |
|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -135,7 +135,7 @@ If running in production, it might be easier to use a 3rd party SMTP server as i
| `_APP_STORAGE_LINODE_ACCESS_KEY` | **version >= 0.14.2** Linode object storage access key. Required when the storage adapter is set to Linode. You can get your access key from your Linode console. |
| `_APP_STORAGE_LINODE_SECRET` | **version >= 0.14.2** Linode object storage secret key. Required when the storage adapter is set to Linode
## Functions {% #functions %}
# Functions {% #functions %}
| **Name** | **Description** |
|-------------------------------|-----------------|
| `_APP_FUNCTIONS_SIZE_LIMIT` | **version >= 0.13.0** The maximum size deployment in bytes. The default value is 30MB. |
@@ -160,7 +160,7 @@ If running in production, it might be easier to use a 3rd party SMTP server as i
| `_APP_DOCKER_HUB_PASSWORD` | **version >= 1.2.0** The password for hub.docker.com. This variable is used to pull images from hub.docker.com. |
| `_APP_FUNCTIONS_MAINTENANCE_INTERVAL`| **version >= 1.4.0** Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour). |
## VCS (Version Control System) {% #vcs %}
# VCS (Version Control System) {% #vcs %}
| **Name** | **Description** |
|---------------------------------|-----------------------------------------------------------------------------------------------------------------|
@@ -172,7 +172,7 @@ If running in production, it might be easier to use a 3rd party SMTP server as i
| `_APP_VCS_GITHUB_WEBHOOK_SECRET`| **version >= 1.4.0** - GitHub webhook secret. You can configure it in your GitHub application settings under webhook section. |
## Maintenance {% #maintenance %}
# Maintenance {% #maintenance %}
| **Name** | **Description** |
|-------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `_APP_MAINTENANCE_INTERVAL` | **version >= 0.7.0** - Interval value containing the number of seconds that the Appwrite maintenance process should wait before executing system cleanups and optimizations. The default value is `86400` seconds (1 day). |
@@ -183,7 +183,7 @@ If running in production, it might be easier to use a 3rd party SMTP server as i
| `_APP_MAINTENANCE_RETENTION_USAGE_HOURLY` | The maximum duration (in seconds) upto which to retain hourly usage metrics. The default value is `8640000` seconds (100 days). |
| `_APP_MAINTENANCE_RETENTION_SCHEDULES` | Schedules deletion interval (in seconds). |
## GraphQL {% #graphql %}
# GraphQL {% #graphql %}
| **Name** | **Description** |
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -191,13 +191,13 @@ If running in production, it might be easier to use a 3rd party SMTP server as i
| `_APP_GRAPHQL_MAX_COMPLEXITY` | **version >= 1.2.0** - Maximum complexity of a GraphQL query. One field adds one to query complexity. Lists multiply the complexity by the number of items requested. The default value is 250. |
| `_APP_GRAPHQL_MAX_DEPTH` | **version >= 1.2.0** - Maximum depth of a GraphQL query. One nested field level adds one to query depth. The default value is 3. |
## Migrations {% #migrations %}
# Migrations {% #migrations %}
| **Name** | **Description** |
|-------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| `_APP_MIGRATIONS_FIREBASE_CLIENT_ID` | **version >= 1.4.0** - Google OAuth client ID. You can find it in your GCP application settings. |
| `_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET` | **version >= 1.4.0** - Google OAuth client secret. You can generate secrets in your GCP application settings. |
## Assistant {% #assistant %}
# Assistant {% #assistant %}
| **Name** | **Description** |
|----------------------------------------|-------------------------------------------------------------------------|
| `_APP_ASSISTANT_OPENAI_API_KEY` | **version >= 1.4.0** - OpenAI API key. You can find it in your OpenAI application settings. |

View File

@@ -4,21 +4,21 @@ title: Functions
description: Harness the full power of self-hosted functions with Appwrite. Explore function deployment, management, and integration in your self-hosted environment.
---
## Configure GitHub app {% #git %}
# Configure GitHub app {% #git %}
Appwrite supports automatic deployments through Git integration. In order for Appwrite to access your repos, you must [create a GitHub app](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps) to enable this integration. The GitHub app requires the following configurations.
For automatic Git deployment to work, Appwrite needs to receive communication from GitHub, this means your Appwrite project must be accessible on the internet. If you're running on `localhost`, you need to run a proxy like [ngrok](https://ngrok.com/).
### GitHub App name {% #github-app-name %}
## GitHub App name {% #github-app-name %}
The GitHub App name will be displayed when connecting Appwrite to GitHub. In addition, this name will be transformed to a slug ("My GitHub App" will become "my-github-app") and appear in the URL when accessing your app in GitHub. This slug should be set as the `_APP_VCS_GITHUB_APP_NAME` environment variable in Appwrite.
### Homepage URL {% #github-homepage-url %}
## Homepage URL {% #github-homepage-url %}
The homepage URL will appear when looking at the public page of your app. It can be any URL you'd like.
### Callback URL {% #callback %}
## Callback URL {% #callback %}
GitHub will use **callback URLs** to redirect users back to Appwrite. Set these callback URLs under **Identifying and authorizing users** in the same order as listed below.
@@ -29,17 +29,17 @@ GitHub will use **callback URLs** to redirect users back to Appwrite. Set these
Also, check the **Request user authentication (OAuth) during installation** box.
### Post installation {% #post-install %}
## Post installation {% #post-install %}
Check the **Redirect on update** box under the **Post installation** section.
### Webhook {% #github-webhooks %}
## Webhook {% #github-webhooks %}
GitHub will notify Appwrite about events like new commits using webhooks. Under **Webhook**, you need to check the **Active** checkbox. You also need to set the **Webhook URL** as `https://[HOSTNAME_OR_IP]/v1/vcs/github/events`.
If you're running Appwrite on `localhost`, GitHub can't send requests to Appwrite through webhooks and automatic deployments won't work. You'll need to host Appwrite on a server or use a proxy like [ngrok](https://ngrok.com/) to make Appwrite accessible to GitHub.
### Repository permissions {% #repository-permission %}
## Repository permissions {% #repository-permission %}
Configure these permissions under the **Repository permission** dropdown.
@@ -54,7 +54,7 @@ Configure these permissions under the **Repository permission** dropdown.
| Pull requests | Read and write |
| Webhooks | Read and write |
### Account permissions {% #account-permission %}
## Account permissions {% #account-permission %}
Configure these permissions under the **Account Permission** dropdown.
@@ -62,7 +62,7 @@ Configure these permissions under the **Account Permission** dropdown.
| -------------- | -------- |
| Email address | Read-only|
### Subscribe to events {% #subscribe-events %}
## Subscribe to events {% #subscribe-events %}
Select these under the **Subscribe to events** dropdown.
@@ -71,11 +71,11 @@ Select these under the **Subscribe to events** dropdown.
| Pull request |
| Push |
### Where can this GitHub App be installed? {% #github-where-installed %}
## Where can this GitHub App be installed? {% #github-where-installed %}
Check the **Any account** box under **Where can this GitHub App be installed?** section. This is important to allow you to install the GitHub app on multiple Appwrite projects.
### Environment variables {% #github-variables %}
## Environment variables {% #github-variables %}
After creating your app, you'll have to configure the following environment variables.
@@ -107,14 +107,14 @@ _APP_VCS_GITHUB_WEBHOOK_SECRET=super-secret
[Learn more about environment variables](/docs/advanced/self-hosting/environment-variables)
### Update exiting GitHub apps {% #existing-apps %}
## Update exiting GitHub apps {% #existing-apps %}
There are additional steps if you're updating permissions in existing GitHub apps.
Every time you update your GitHub app's permissions, GitHub will prompt you to review the changes.
You will receive an email and you'll find a prompt under **Settings** > **Integrations** > **Applications** > **Installed GitHub Apps** > find your GitHub app > **Configure**.
You need to accept the new permissions so they're applied to your app.
## Configure Function runtimes {% #functions %}
# Configure Function runtimes {% #functions %}
Not all function runtimes are enabled by default. Enable the runtimes that you need and disable unused runtimes to save disk space on your server.
To enable a runtime, add it to the `_APP_FUNCTIONS_RUNTIMES` environment variable as a comma-separated list.

View File

@@ -6,7 +6,7 @@ description: Set up your self-hosted Appwrite instance with ease. Follow the ins
Appwrite was designed from the ground up with self-hosting in mind. You can install and run Appwrite on any operating system that can run a [Docker CLI](https://www.docker.com/products/docker-desktop). Self-hosted Appwrite instances can be configured flexibly with access to the same features found on Appwrite Cloud.
## System requirements {% #system-requirements %}
# System requirements {% #system-requirements %}
Appwrite is designed to run well on both small and large deployments. The minimum requirements to run Appwrite are as little as **1 CPU core** and **2GB of RAM**, and an operating system that supports Docker.
@@ -16,7 +16,7 @@ Appwrite requires [Docker Compose Version 2](https://docs.docker.com/compose/ins
If you are migrating from an older version of Appwrite, you need to follow the [migration instructions](/docs/advanced/self-hosting/update)
{% /info %}
## Install with Docker {% #install-with-docker %}
# Install with Docker {% #install-with-docker %}
The easiest way to start running your Appwrite server is by running our Docker installer tool from your terminal. Before running the installation command, make sure you have [Docker CLI](https://www.docker.com/products/docker-desktop) installed on your host machine.
@@ -29,7 +29,7 @@ You will be prompted to configure the following during the setup command:
{% tabs %}
{% tabsitem #unix title="macOS and Linux" %}
### Bash
## Bash
```sh
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
@@ -40,7 +40,7 @@ docker run -it --rm \
{% /tabsitem %}
{% tabsitem #windows title="Windows" %}
### CMD
## CMD
```cmd
docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
@@ -48,7 +48,7 @@ docker run -it --rm ^
--entrypoint="install" ^
appwrite/appwrite:1.4.3
```
### Powershell
## Powershell
```powershell
docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock `
@@ -59,7 +59,7 @@ docker run -it --rm `
{% /tabsitem %}
{% /tabs %}
## One-click setups {% #one-click-setups %}
# One-click setups {% #one-click-setups %}
In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running with Appwrite quickly without installing Docker on your local machine.
@@ -87,7 +87,7 @@ Choose from one of the providers below:
{% /table %}
## Next steps {% #next-steps %}
# Next steps {% #next-steps %}
Self-hosting Appwrite gives you more configurable options.
Make these configurations to unlock the full power of Appwrite.
@@ -102,7 +102,7 @@ Make these configurations to unlock the full power of Appwrite.
[Configure TLS Certificates](/docs/advanced/self-hosting/tls-certificates)
## Manual (Docker Compose) {% #manual %}
# Manual (Docker Compose) {% #manual %}
For advanced Docker users, the manual installation might seem more familiar. To set up Appwrite manually, download the Appwrite base `docker-compose.yml` and `.env` files, then move them inside a directory named `appwrite`. After the download completes, update the different environment variables as you wish in the `.env` file and start the Appwrite stack using the following Docker command:
@@ -112,7 +112,7 @@ docker compose up -d --remove-orphans
Once the Docker installation completes, go to your machine's hostname or IP address on your browser to access the Appwrite Console. Please note that on hosts that are not Linux-native, the server might take a few minutes to start after installation completes.
## Stop {% #stop %}
# Stop {% #stop %}
You can stop your Appwrite containers by using the following command executed from the same directory as your `docker-compose.yml` file.
@@ -120,7 +120,7 @@ You can stop your Appwrite containers by using the following command executed fr
docker compose stop
```
## Uninstall {% #uninstall %}
# Uninstall {% #uninstall %}
To stop and remove your Appwrite containers, you can use the following command executed from the same directory as your `docker-compose.yml` file.

View File

@@ -6,7 +6,7 @@ description: Optimize self-hosted Appwrite for production environments. Learn ho
Appwrite's default setup is designed to help you start building with Appwrite quickly. To succeed with Appwrite in a production environment, you should follow a few basic concepts and best practices. This document assumes you have some basic understanding of Docker and Docker Compose command-line tools.
## Encryption {% #encryption %}
# Encryption {% #encryption %}
Appwrite does not generate a unique encryption key during a default setup. This key encrypts your files and sensitive data like webhook passwords or API keys to keep them secure. To take advantage of this feature, you must generate a unique key and set it as the value of the `_APP_OPENSSL_KEY_V1` environment variable.
@@ -19,7 +19,7 @@ You should always prefer **HTTPS** over HTTP in production environments. This ke
You can force the use of HTTPS with the [_APP_OPTIONS_FORCE_HTTPS](/docs/advanced/self-hosting/environment-variables) environment variable.
{% /info %}
## Console access {% #console-access %}
# Console access {% #console-access %}
Appwrite provides three different methods to limit access to your Appwrite Console.
@@ -31,7 +31,7 @@ By default, only the first user can sign up on the Appwrite instance's dashboard
[Learn more about environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Scaling {% #scaling %}
# Scaling {% #scaling %}
Appwrite is built with scalability in mind. Appwrite can scale both horizontally and vertically.
@@ -41,7 +41,7 @@ If you decide to set up a load balancer to scale a container, make sure **all**
Three Appwrite containers are stateful. The MariaDB, Redis, and InfluxDB containers are used for storing data, cache and pub/sub messaging, and usage stats, respectively. To scale these containers, set up a standard cluster (same as you would with any other app using these technologies) according to your needs and performance.
## Rate limits {% #rate-limits %}
# Rate limits {% #rate-limits %}
If you disabled rate limits during development, make sure you re-enable them when moving to production environments. Rate limiting can be enabled by setting the `_APP_OPTIONS_ABUSE` environment variable to `enabled`.
@@ -49,13 +49,13 @@ Rate limits are an important mechanism to protect your app. Without rate limits,
[Learn more about environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Emails {% #emails %}
# Emails {% #emails %}
Sending emails is hard. There are a lot of spam rules and configurations to master in order to set up a functional SMTP server. While it is okay to use a self-hosted SMTP server during development, you should use a third-party SMTP provider for production so your email doesn't get labeled as spam.
You can [change Appwrite's SMTP settings](/docs/advanced/self-hosting/email) and credentials to any 3rd party provider you like that supports SMTP integration using our Docker environment variables. Most SMTP providers offer a decent free tier to get started with.
## Backups {% #backups %}
# Backups {% #backups %}
Backups are highly recommended for any production environment. Currently, there is no built-in script we provide to do this automatically. You must do the following to back up your Appwrite server data, stats, and files.
@@ -68,7 +68,7 @@ Backups are highly recommended for any production environment. Currently, there
Do not back up any stateful container using a docker volume backup, such as databases, Redis, or InfluxDB containers. This can result in corruption and **permanent data loss**.
{% /info %}
## Errors {% #errors %}
# Errors {% #errors %}
By default, your Appwrite installation comes with error reporting turned off. You can [enable dev mode](/docs/advanced/self-hosting/debug#development-mode) to get access to more verbose error logs and stack traces.
@@ -80,7 +80,7 @@ In production, it is highly recommended to turn error reporting off. To do so, m
[Learn more about environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Security {% #security %}
# Security {% #security %}
In addition to the security practices mentioned, it is highly recommended to do regular audits to identify and fix potential security vulnerabilities and performance issues. You can use third-party tools and services that specialize in these areas. These tools can automatically check for vulnerabilities and even offer real-time monitoring.

View File

@@ -6,7 +6,7 @@ description: Set up SMS services for your self-hosted Appwrite instance. Discove
Appwrite supports phone authentication, which allows users to create accounts and log in using SMS messages. Appwrite requires an SMS provider to be set up before using Phone authentication.
## SMS providers {% #sms-providers %}
# SMS providers {% #sms-providers %}
Appwrite supports a growing list of SMS providers that you can choose from. Choose one from the list below and set up an account.
@@ -47,7 +47,7 @@ Appwrite supports a growing list of SMS providers that you can choose from. Choo
* [Documentation](https://developer.vonage.com/en/account/secret-management)
{% /table %}
## Environment variables {% #environment-variables %}
# Environment variables {% #environment-variables %}
You will need to configure these [environment variables](https://example.com/docs/environment-variables#phone) and restart your Appwrite containers before you can use phone authentication.

View File

@@ -8,7 +8,7 @@ Appwrite's Storage Service can be configured to store files locally, or with sel
By default, Appwrite's Storage Service **stores files on your server's local storage**.
If you expect large volumes of data or the need to have scalable data storage, you may choose to use a separate storage service.
## Available adpters {% #adapters %}
# Available adpters {% #adapters %}
Appwrite supports AWS S3, Digital Ocean Spaces, Backblaze, Akamai Object Storage, and Wasabi as storage adapters.
Some of these services can be self-hosted, just like Appwrite.
@@ -16,7 +16,7 @@ You can select which storage adapter to use by setting the `_APP_STORAGE_DEVICE`
[Learn more about storage environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Maximum file size {% #adapters %}
# Maximum file size {% #adapters %}
The maximum size for a single file upload is controlled by the `_APP_STORAGE_LIMIT` environment variable, which defaults to 30 MB.
[Learn more about environment variables](/docs/advanced/self-hosting/environment-variables).

View File

@@ -11,7 +11,7 @@ Appwrite uses Let's Encrypt to auto-generate TLS certificates for your Appwrite
3. You need to ensure you have a valid email address set on `_APP_SYSTEM_SECURITY_EMAIL_ADDRESS`. The default setup comes with `certs@appwrite.io` as the default value. While this address will work, it's recommended to change it to your own email.
4. Currently, Appwrite is using the [ACME](https://letsencrypt.org/docs/client-options/) HTTP challenge to issue an TLS certificate. This forces us to generate certificates for port 443 when the challenge itself is performed on port 80. At this point, other ports will not work. To overcome this limit, you can set Appwrite on a separate sub-domain or use your own certificate or proxy server in front of Appwrite.
## Debugging
# Debugging
If you're still struggling with your certificates, check the Appwrite certificates worker log. You can do that with the following command:
@@ -19,13 +19,13 @@ If you're still struggling with your certificates, check the Appwrite certificat
docker compose logs appwrite-worker-certificates
```
## Generation cycle
# Generation cycle
Appwrite auto-generates a certificate for your main domain when you first visit it. If your browser shows an insecure connection warning, you must proceed to trigger certificate generation. The domain in environment variable `_APP_DOMAIN` is considered your main domain. If you didn't set this variable, the first domain you visit would be marked as the main domain for your Appwrite instance. Appwrite follows this concept of the main domain to prevent generating certificates for domains you don't own. Keep in mind that you can always add additional domains as **Custom Domains** in your project settings to enable certificate generation for any domain.
Certificate renewal is done as a part of the Appwrite maintenance task. Unless modified with environment variable `_APP_MAINTENANCE_INTERVAL`, this task runs every 24 hours. During this task, Appwrite looks for certificates due for renewal and renews them. One maintenance cycle only attempts to renew up to 200 certificates to respect the Let's Encrypt API limit. Every Let's Encrypt certificate is valid for 90 days, but Appwrite starts to renew them 30 days before the expiration.
## Manual generation
# Manual generation
Since Appwrite generates and renews certificates automatically, a manual generation is seldom required. A manual generation can be useful when you hit the API limit and don't want to wait for the next maintenance cycle to renew the certificate. Use the following command to generate a certificate for your main domain:
@@ -39,7 +39,7 @@ If you want to generate a certificate for a specific domain, pass it as a parame
docker compose exec appwrite ssl domain="api.myapp.com"
```
## Development environment and localhost
# Development environment and localhost
You can't issue a [signed certificate for localhost](https://letsencrypt.org/docs/certificates-for-localhost/). This is because nobody uniquely owns that hostname and not an Appwrite specific limitation, just the way the internet works. By default, Appwrite will issue a self-signed certificate that is good enough for development.

View File

@@ -26,9 +26,9 @@ parent_directory <= you run the command in this directory
This is the parent directory where you will find the `appwrite directory, inside which there are `docker-compose.yml` and `.env` files.
## Installing the next version {% #install-next-version %}
# Installing the next version {% #install-next-version %}
### Unix
## Unix
```sh
docker run -it --rm \
@@ -38,7 +38,7 @@ docker run -it --rm \
appwrite/appwrite:1.4.3
```
### CMD
## CMD
```cmd
docker run -it --rm ^
@@ -48,7 +48,7 @@ docker run -it --rm ^
appwrite/appwrite:1.4.3
```
### PowerShell
## PowerShell
```powershell
docker run -it --rm `
@@ -66,7 +66,7 @@ docker ps | grep appwrite/appwrite
```
Verify that the `STATUS` doesn't have any errors and all the `appwrite/appwrite` containers have the same version.
## Running the Migration
# Running the Migration
We can now start the migration. Navigate to the `appwrite` directory where your `docker-compose.yml` is present and run the following command.
```sh

View File

@@ -9,7 +9,7 @@ Appwrite supports multiple protocols for accessing the server, including [REST](
The GraphQL API allows you to query and mutate any resource type on your Appwrite server through the endpoint `/v1/graphql`.
Every endpoint available through REST is available through GraphQL, except for OAuth.
## Requests {% #requests %}
# Requests {% #requests %}
Although every query executes through the same endpoint, there are multiple ways to make a GraphQL request. All requests, however, share a common structure.
@@ -19,17 +19,17 @@ Although every query executes through the same endpoint, there are multiple ways
| operationName | string | **Optional**, if the query contains several named operations, controls which one to execute. |
| variables | object | **Optional**, an object containing variable names and values for the query. Variables are made available to your query with the `$` prefix. |
### GraphQL model parameters {% #graphql-model-parameters %}
## GraphQL model parameters {% #graphql-model-parameters %}
In Appwrite's GraphQL API, all internal model parameters are prefixed with `_` instead of `$` because `$` is reserved by GraphQL.
For example, `$collectionId` in the REST API would be referenced as `_collectionId` in the GraphQL API.
### GET requests {% #get-resquest %}
## GET requests {% #get-resquest %}
You can execute a GraphQL query via a GET request, passing a `query` and optionally `operationName` and `variables` as query parameters.
### POST requests {% #post-request %}
## POST requests {% #post-request %}
There are multiple ways to make a GraphQL POST request, differentiated by content type.
@@ -39,7 +39,7 @@ There are multiple ways to make a GraphQL POST request, differentiated by conten
There are two ways to make requests with the `application/json` content type.
You can send a JSON object containing a `query` and optionally `operationName` and `variables`, or an array of objects with the same structure.
#### Object
### Object
```json
{
@@ -49,7 +49,7 @@ You can send a JSON object containing a `query` and optionally `operationName` a
}
```
#### Array
### Array
```json
[
@@ -77,7 +77,7 @@ query GetAccount {
{% /tabs %}
### Multipart form data {% #multipart-form-data %}
## Multipart form data {% #multipart-form-data %}
The `multipart/form-data` content type can be used to upload files via GraphQL.
In this case, the form data must include the following parts in addition to the files to upload.
@@ -87,7 +87,7 @@ In this case, the form data must include the following parts in addition to the
| operations |string | **Required**, JSON encoded GraphQL query and optionally operation name and variables. File variables should contain null values. |
| map | string | **Required**, JSON encoded map of form-data filenames to the operations dot-path to inject the file to, e.g. `variables.file`. |
## Responses {% #responses %}
# Responses {% #responses %}
A response to a GraphQL request will have the following structure:
@@ -103,7 +103,7 @@ The errors array will contain error objects, each with their own **message** and
The path will contain the field key that is null due to the error.
If no errors occur, the array will not be present in the response.
## Authentication {% #authentication %}
# Authentication {% #authentication %}
GraphQL authenticates using Appwrite accounts and sessions.
Both accounts and sessions can be created with GraphQL using the `accountCreate`, `accountCreateEmailSession`,
@@ -111,11 +111,11 @@ Both accounts and sessions can be created with GraphQL using the `accountCreate`
More information and examples of authenticating users can be found in the dedicated [authentication guide](/docs/products/auth).
## GraphQL vs REST {% #graphql-vs-rest %}
# GraphQL vs REST {% #graphql-vs-rest %}
There are two main features that make GraphQL appealing when compared to the REST API: **selection sets** and **query batching**.
### Selection sets {% #selection-sets %}
## Selection sets {% #selection-sets %}
Selection sets can be used to tell a GraphQL API exactly which fields of a particular resource you would like to receive in the response.
The server will respond with only those fields, nothing more, nothing less. This gives you full control over what data comes into your application.
@@ -148,7 +148,7 @@ Given this query, the GraphQL API will respond with:
This can be a useful feature for performance, network efficiency, and app responsiveness.
As the processing happens on the server, the bandwidth consumed for the request can be dramatically reduced.
## Query batching {% #query-batching %}
# Query batching {% #query-batching %}
GraphQL allows sending multiple queries or mutations in the same request.
There are two different ways to batch queries. The simplest way is to include multiple fields in a single query **or** mutation.
@@ -224,7 +224,7 @@ In this way, you can execute queries **and** mutations and keep variables separa
This allows you to execute complex actions in a single network request.
## SDK usage {% #sdk-usage %}
# SDK usage {% #sdk-usage %}
Appwrite SDKs also support GraphQL in addition to the REST services.

View File

@@ -100,16 +100,16 @@ All subscriptions are secured by the [permissions system](/docs/advanced/platfor
Using `Role.any()` on read permissions will allow any client to receive updates.
{% /info %}
## Authentication {% #authentication %}
# Authentication {% #authentication %}
Realtime authenticates using an existing user session. If you authenticate **after** creating a subscription, the subscription will not receive updates for the newly authenticated user. You will need to re-create the subscription to work with the new user.
More information and examples of authenticating users can be found in the dedicated [authentication docs](/docs/products/auth).
## Examples {% #examples %}
# Examples {% #examples %}
The examples below will show you how you can use Realtime in various ways.
### Subscribe to a Channel
## Subscribe to a Channel
In this example we are subscribing to all updates related to our account by using the `account` channel. This will be triggered by any update related to the authenticated user, like updating the user's name or e-mail address.
{% multicode %}
@@ -177,7 +177,7 @@ val subscription = realtime.subscribe("account") {
{% /multicode %}
### Subscribe to Multiple Channels
## Subscribe to Multiple Channels
You can also listen to multiple channels at once by passing an array of channels. This will trigger the callback for any events for all channels passed.
@@ -247,7 +247,7 @@ realtime.subscribe("databases.A.collections.A.documents.A", "files") {
{% /multicode %}
### Unsubscribe
## Unsubscribe
If you no longer want to receive updates from a subscription, you can unsubscribe so that your callbacks are no longer called. Leaving old subscriptions alive and resubscribing can result in duplicate subscriptions and cause race conditions.
@@ -324,7 +324,7 @@ subscription.close()
{% /multicode %}
## Payload {% #payload %}
# Payload {% #payload %}
The payload from the subscription will contain following properties:
@@ -410,7 +410,7 @@ The response will look like this:
}
```
## Channels {% #channels %}
# Channels {% #channels %}
A list of all channels available you can subscribe to. IDs cannot be wildcards.
@@ -462,7 +462,7 @@ A list of all channels available you can subscribe to. IDs cannot be wildcards.
{% /table %}
## Custom endpoint {% #custom-endpoint %}
# Custom endpoint {% #custom-endpoint %}
The SDK will guess the endpoint of the Realtime API when setting the endpoint of your Appwrite instance. If you are running Appwrite with a custom proxy and changed the route of the Realtime API, you can call the `setEndpointRealtime` method on the Client SDK and set your new endpoint value.
@@ -499,14 +499,14 @@ client.setEndpointRealtime("wss://cloud.appwrite.io/v1/realtime")
{% /multicode %}
## Limitations {% #limitations %}
# Limitations {% #limitations %}
While the Realtime API offers robust capabilities, there are currently some limitations to be aware of in its implementation.
### Subscriptions changes
## Subscriptions changes
The SDK creates a single WebSocket connection for all subscribed channels. Each time a channel is added or unsubscribed - the SDK currently creates a completely new connection and terminates the old one. Therefore, subscriptions to channels should always be done in conjunction with state management so as not to be unnecessarily built up several times by multiple components' life cycles.
### Server-side SDKs
## Server-side SDKs
We currently are not offering access to realtime with Server SDKs and an API key.

View File

@@ -6,7 +6,7 @@ description: Discover the Appwrite REST API for building robust and scalable app
Appwrite supports multiple protocols for accessing the server, including [REST](/docs/apis/rest), [GraphQL](/docs/apis/graphql), and [Realtime](/docs/apis/realtime). The REST API allows you to access your Appwrite server through HTTP requests without the needing an SDK. Each endpoint in the API represents a specific operation on a specific resource.
## Headers {% #headers %}
# Headers {% #headers %}
Appwrite's REST APIs expect certain headers to be included with each request:
@@ -41,11 +41,11 @@ Appwrite's REST APIs expect certain headers to be included with each request:
---
{% /table %}
## Authentication {% #authentication %}
# Authentication {% #authentication %}
Appwrite supports multiple authentication methods, including account sessions, API keys, and JWTs. The authentication method you use depends on your use case. Below are examples showing how you can authenticate using the REST API.
### Client side
## Client side
You can create account sessions with POST requests to the Account API. Sessions are persisted using secured cookies. You can learn more about session persistence in the Authentication Guide.
@@ -78,7 +78,7 @@ Content-Type: application/json
X-Appwrite-Project: [PROJECT_ID]
```
### Server side
## Server side
Server integrations use API keys to authenticate and are typically used for backend applications.
@@ -91,7 +91,7 @@ X-Appwrite-Project: [PROJECT_ID]
X-Appwrite-Key: [API_KEY]
```
### JWT
## JWT
JWT authentication is frequently used by server applications to act on behalf of a user. Users generate tokens using the [Create JWT](/docs/references/cloud/client-web/account#createJWT) endpoint. When issuing requests authenticated with a JWT, Appwrite will treat the request like it is from the authenticated user.
@@ -102,7 +102,7 @@ X-Appwrite-Project: [PROJECT_ID]
X-Appwrite-JWT: [TOKEN]
```
## Files {% #files %}
# Files {% #files %}
Appwrite implements resumable, chunked uploads for files larger than 5MB. Chunked uploads send files in chunks of 5MB to reduce memory footprint and increase resilience when handling large files. Appwrite SDKs will automatically handle chunked uploads, but it is possible to implement this with the REST API directly.
@@ -191,7 +191,7 @@ read("user:627a958ded6424a98a9f")
------WebKitFormBoundarye0m6iNBQNHlzTpVM--
```
## Images {% #images %}
# Images {% #images %}
Some use cases do not allow custom headers, such as embedding images from Appwrite in HTML. In these cases, you can provide the Appwrite project ID using the query parameter project.
@@ -199,7 +199,7 @@ Some use cases do not allow custom headers, such as embedding images from Appwri
<img src="[ENDPOINT]/v1/storage/buckets/[BUCKET_ID]/files/[FILE_ID]/preview?project=[PROJECT_ID]"/>
```
## Permissions {% #permissions %}
# Permissions {% #permissions %}
Appwrite SDKs have helpers to generate permission string formats, but when using Appwrite without SDKs, you'd need to create the strings yourself.
@@ -224,7 +224,7 @@ Appwrite SDKs have helpers to generate permission string formats, but when using
---
{% /table %}
### Roles
## Roles
Appwrite SDKs have helpers to generate roles string formats, but when using Appwrite without SDKs, you'd need to create the strings yourself.
@@ -261,11 +261,11 @@ Appwrite SDKs have helpers to generate roles string formats, but when using Appw
---
{% /table %}
## Unique ID {% #unique-id %}
# Unique ID {% #unique-id %}
Appwrite's SDKs have a helper `ID.unique()` to generate unique IDs. When using Appwrite without an SDK, pass the string `"unique()"` into the ID parameter.
## Queries {% #queries %}
# Queries {% #queries %}
Appwrite's SDKs provide a `Query` class to generate query strings. When using Appwrite without an SDK, you can template your own strings with the format below.
@@ -339,13 +339,13 @@ When using greater than, greater than or equal to, less than, or less than or eq
{% /info %}
## Rate limits {% #rate-limits %}
# Rate limits {% #rate-limits %}
Appwrite's REST APIs are protected by the same rate limit policies, just like when using an SDK. Each API has a different rate limit, which is documented in the References section of each service in the Appwrite documentation.
[Learn more about Rate Limits](/docs/advanced/platform/rate-limits).
## Specifications {% #specifications %}
# Specifications {% #specifications %}
Appwrite provides a full REST API specification in the OpenAPI 3 and Swagger 2 formats every release. These can be accessed through Appwrite's GitHub repository and rendered using a variety of parsers and tools.

View File

@@ -10,7 +10,7 @@ Each user's account can also have their own preference object, which you can use
{% partial file="account-vs-user.md" /%}
## Signup and login {% #signup-login %}
# Signup and login {% #signup-login %}
You can signup and login a user with an account create through
[email password](/docs/products/auth/email-password),
@@ -20,7 +20,7 @@ You can signup and login a user with an account create through
[OAuth 2](/docs/products/auth/oauth2)
authentication.
## Preferences {% #preferences %}
# Preferences {% #preferences %}
You can store user preferences on a user's account using Appwrite's [Update Preferences](/docs/references/cloud/client-web/account#updatePrefs) endpoint. You can store preferences such as theme, notification settings, or preferred language so they can be synced across multiple devices.
@@ -171,7 +171,7 @@ query {
```
{% /multicode %}
## Permissions {% #permissions %}
# Permissions {% #permissions %}
You can grant permissions to all users using the `Role.users(<STATUS>)` role or
individual users using the `Role.user(<USER_ID>, <STATUS>)` role.

View File

@@ -8,7 +8,7 @@ Anonymous sessions allow you to implement **guest** users. Guest users let you s
**If a user later creates an account**, their information will be inherited by the newly created account.
## Create anonymous session {% #createSession %}
# Create anonymous session {% #createSession %}
Create an anonymous session with [Create Anonymous Session](/docs/references/cloud/client-web/account#createAnonymousSession) route.
@@ -76,7 +76,7 @@ mutation {
```
{% /multicode %}
## Attaching an account {% #attach-account %}
# Attaching an account {% #attach-account %}
Anonymous users cannot sign back in. If the session expires, they move to another computer, or they clear their browser data, they won't be able to log in again. Remember to prompt the user to create an account to not lose their data.

View File

@@ -6,7 +6,7 @@ description: Implement email and password authentication with Appwrite. Securely
Email and password login is the most commonly used authentication method. Appwrite Authentication promotes a safer internet by providing secure APIs and promoting better password choices to end users. Appwrite supports added security features like blocking personal info in passwords, password dictionary, and password history to help users choose good passwords.
## Signup {% #sign-up %}
# Signup {% #sign-up %}
You can use the Appwrite Client SDKs to create an account using email and password.
@@ -30,7 +30,7 @@ promise.then(function (response) {
Passwords are hashed with [Argon2](https://github.com/P-H-C/phc-winner-argon2), a resilient and secure password hashing algorithm.
## Verification {% #verification %}
# Verification {% #verification %}
After an account is created, it can be verified through the account create verification route. The user doesn't need to be verified to log in, but you can restrict resource access to verified users only using permissions through the `user([USER_ID], "verified")` role.
@@ -80,7 +80,7 @@ promise.then(function (response) {
});
```
## Login {% #login %}
# Login {% #login %}
After you've created your account, users can be logged in using the Create Email Session route.
@@ -102,7 +102,7 @@ promise.then(function (response) {
});
```
## Password Recovery {% #password-recovery %}
# Password Recovery {% #password-recovery %}
If a user forgets their password, they can initiate a password recovery flow to recover their password. The Create Password Recovery endpoint sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link, they are redirected back to the password reset URL with the secret key and email address values attached to the URL as query strings.
@@ -147,6 +147,6 @@ promise.then(function (response) {
});
```
## Security {% #security %}
# Security {% #security %}
Appwrite's security first mindset goes beyond a securely implemented of authentication API. You can enable features like password dictionary, password history, and disallow personal data in passwords to encourage users to pick better passwords. By enabling these features, you protect user data and teach better password choices, which helps make the internet a safer place.

View File

@@ -8,13 +8,13 @@ You can extend Appwrite's APIs by building backend apps using [Server SDKs](/doc
If you are already authenticated on your client-side app and need your backend app to **act on behalf of the user**, this guide will walk you through the process.
## Proof of Identity {% #proof-of-identity %}
# Proof of Identity {% #proof-of-identity %}
Before making requests to your backend APIs, your client application needs to first create a session **directly with Appwrite** using the account service. This session will act like an ID card for the user and can be used to access resources in Appwrite. The client will **only receive information accessible to the user** based on the resources' [permissions](/docs/advanced/platform/permissions).
When you build backend APIs to extend Appwrite's functionality, these APIs should still **respect access permissions** to keep user data secure. Appwrite's backend SDKs allow you to securely act on behalf of a user with the same permissions by using JWT authentication.
## JWT Authentication {% #jwt %}
# JWT Authentication {% #jwt %}
[JSON Web Tokens](https://jwt.io/introduction) (JWTs) are a secure means to transfer information or claims between two parties. JWTs act like temporary copies of the user's ID card that allow Appwrite's Server SDKs to access information on behalf of a user.
@@ -169,7 +169,7 @@ var client = new Client()
{% /multicode %}
## When should I use JWTs? {% #when-to-use %}
# When should I use JWTs? {% #when-to-use %}
JWT auth is useful when you need your backend app's Server SDK to be restricted by the same set of permissions.
@@ -177,7 +177,7 @@ If your backend app's Server SDK is using an [API key](/docs/advanced/platform/a
If your backend app's Server SDK is using a **JWT**, it will only fetch resources your user has permissions to access.
## Example {% #when-to-use-example %}
# Example {% #when-to-use-example %}
Here's an example collection of birthdays with the following documents. Notice how they all have **different permissions**.

View File

@@ -6,7 +6,7 @@ description: Add magic URL to your authentication in Appwrite. Explore the conve
Magic URL is a password-less way to authenticate users. When a user logs in by providing their email, they will receive an email with a "magic" link that contains a secret used to log in the user. The user can simply click the link to be logged in.
## Send email {% #init %}
# Send email {% #init %}
Initialize the log in process with the [Create Magic URL Session](/docs/references/cloud/client-web/account#createMagicURLSession) route. If the email has never been used, a **new account is generated**, then the user will receive an email. If the email is already attached to an account, the **user ID is ignored** and the user will receive a link in their email.
@@ -46,7 +46,7 @@ mutation {
{% /multicode %}
## Login {% #login %}
# Login {% #login %}
After receiving your secret from an email, you can create a session.

View File

@@ -8,7 +8,7 @@ OAuth authentication allows users to log in using accounts from other popular se
When using OAuth to authenticate, the authentication request is initiated from the client application. The user is then redirected to an OAuth 2 provider to complete the authentication step, and finally, the user is redirected back to the client application.
## Configure OAuth 2 login {% #configure %}
# Configure OAuth 2 login {% #configure %}
Before using OAuth 2 login, you need to enable and configure an OAuth 2 login provider.
@@ -20,7 +20,7 @@ Before using OAuth 2 login, you need to enable and configure an OAuth 2 login pr
6. Copy information from your OAuth2 provider's developer platform to fill the **OAuth2 Settings** modal in the Appwrite Console.
7. Configure redirect URL in your OAuth 2 provider's developer platform. Set it to URL provided to you by **OAuth2 Settings** modal in Appwrite Console.
## Initialize OAuth 2 login {% #init %}
# Initialize OAuth 2 login {% #init %}
To initialize the OAuth 2 login process, use the [Create OAuth 2 Session](/docs/references/cloud/client-web/account#createOAuth2Session) route.
@@ -135,7 +135,7 @@ You'll be redirected to the OAuth 2 provider's login page to log in. Once comple
You can optionally configure `success` or `failure` redirect links on web to handle success and failure scenarios.
## OAuth 2 profile {% #profile %}
# OAuth 2 profile {% #profile %}
After authenticating a user through their OAuth 2 provider, you can fetch their profile information such as their avatar image or name. To do this you can use the access token from the OAuth 2 provider and make API calls to the provider.
@@ -232,7 +232,7 @@ An OAuth 2 [session](/docs/references/cloud/models/session) will have the follow
You can use the `providerAccessToken` to make requests to your OAuth 2 provider. Refer to the docs for the OAuth 2 provider you're using to learn about making API calls with the access token.
## OAuth 2 profile {% #profile %}
# OAuth 2 profile {% #profile %}
OAuth 2 sessions expire to protect from security risks. OAuth 2 sessions should be refreshed periodically, so access tokens don't expire. Check value of `providerAccessTokenExpiry` to know if the token is expired or is about to expire. Refreshing before every request might cause rate limit problems. You can do this by calling the [Update OAuth Session](/docs/references/cloud/client-web/account#updateSession) endpoint when ever your user visits your app.

View File

@@ -6,7 +6,7 @@ description: Enhance security with phone and SMS authentication in Appwrite. Dis
Phone authentication lets users create accounts using their phone numbers and log in through SMS messages.
## Send SMS message {% #init %}
# Send SMS message {% #init %}
Phone authentication is done using a two-step authentication process. When using phone authentication, the authentication request is initiated from the client application and an SMS message is sent to the user's phone. The SMS message will contain a secret the user can use to log in.
@@ -97,7 +97,7 @@ mutation {
{% /multicode %}
## Login {% #login %}
# Login {% #login %}
After initiating the phone authentication process, the returned user ID and secret are used to confirm the user. The secret will usually be a 6-digit number in the SMS message sent to the user.

View File

@@ -6,7 +6,7 @@ description: Effortlessly add authentication to your apps - simple signup & logi
You can get up and running with Appwrite Authentication in minutes.
Adding signup and login is as simple as this.
## Sign up {% #sign-up %}
# Sign up {% #sign-up %}
You can use the Appwrite [Client SDKs](/docs/sdks#client) to create an account using email and password.
@@ -87,7 +87,7 @@ mutation {
```
{% /multicode %}
## Login {% #login %}
# Login {% #login %}
After you've created your account, users can be logged in using the [Create Email Session](/docs/references/cloud/client-web/account#createEmailSession) route.
@@ -168,7 +168,7 @@ mutation {
```
{% /multicode %}
## More ways to Authenticate
# More ways to Authenticate
You can signup and login a user with an account create through
[email password](/docs/products/auth/email-password),
[phone (SMS)](/docs/products/auth/phone-sms),

View File

@@ -6,7 +6,7 @@ description: Prioritize security in your applications with Appwrite. Discover be
Appwrite provides many security features to keep both your Appwrite project and your user's information secure.
## Persistence
# Persistence
Appwrite handles the persistence of the session in a consistent way across SDKs. After authenticating with an SDK, the SDK will persist the session so that the user will not need to log in again the next time they open the app. The mechanism for persistence depends on the SDK.
@@ -21,31 +21,31 @@ Only keep user sessions active as long as needed and maintain exactly **one** in
| {% only_dark %}{% icon_image src="/images/platforms/dark/apple.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/apple.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Apple | Uses a session cookie stored in **UserDefaults**. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/android.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/android.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Android | Uses a session cookie stored in **SharedPreferences**. |
## Session limits
# Session limits
In Appwrite versions 1.2 and above, you can limit the number of active sessions created per user to prevent the accumulation of unused but active sessions. New sessions created by the same user past the session limit delete the oldest session.
You can change the session limit in the **Security** tab of the Auth Service in your Appwrite Console. The default session limit is 10 with a maximum configurable limit of 100.
## Permissions
# Permissions
Security is very important to protect users' data and privacy.
Appwrite uses a [permissions model](/docs/advanced/platform/permissions) coupled with user sessions to ensure users need correct permissions to access resources.
With all Appwrite services, including databases and storage, access is granted at the collection, bucket, document, or file level.
These permissions are enforced for client SDKs and server SDKs when using JWT, but are ignored when using a server SDK with an API key.
## Password history
# Password history
Password history prevents users from reusing recent passwords. This protects user accounts from security risks by enforcing a new password every time it's changed.
Password history can be enabled in the Auth service's **Security** tab on the Appwrite Console. You can choose how many previous passwords to remember up to a maximum of 20 and block users from reusing them.
## Password dictionary
# Password dictionary
Password dictionary protects users from using bad passwords. It compares the user's password to the [10,000 most common passwords](https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10k-most-common.txt) and throws an error if there's a match. Together with [rate limits](/docs/advanced/platform/rate-limits), password dictionary will significantly reduce the chance of a malicious actor from guessing user passwords.
Password dictionary can be enabled in the Auth service's **Security** tab on the Appwrite Console.
## Personal data
# Personal data
Encourage passwords that are hard to guess by disallowing users to pick passwords that contain personal data.
Personal data includes the user's name, email, and phone number.

View File

@@ -10,7 +10,7 @@ You can further give special rights to parts of a team using team roles.
The invited user can [accept the invitation](/docs/references/cloud/client-web/teams#updateMembershipStatus) to gain access. If the user's ever removed from the team, they'll lose access again.
## Create team {% #create %}
# Create team {% #create %}
For example, we can create a team called `teachers` with roles `maths`, `sciences`, `arts`, and `literature`.
The creator of the team is also granted the `owner` role. **Only those with the `owner` role can invite and remove members**.
@@ -99,7 +99,7 @@ val response = teams.create(
{% /multicode %}
## Invite a member {% #create-membership %}
# Invite a member {% #create-membership %}
You can invite members to a team by creating team memberships. For example, inviting "David" a math teacher, to the teachers team.
@@ -187,7 +187,7 @@ val response = teams.createMembership(
{% /multicode %}
## Permissions {% #permissions %}
# Permissions {% #permissions %}
You can grant permissions to all members of a team using the `Role.team(<TEAM_ID>)` role or
individual roles in the team using the `Role.team(<TEAM_ID>, [<ROLE_1>, <ROLE_2>, ...])` role.

View File

@@ -8,7 +8,7 @@ The terms collections and documents are used because the Appwrite JSON REST API
That said, Appwrite is designed to support both SQL and NoSQL database adapters like MariaDB, MySQL, or MongoDB in future versions.
## Create collection
# Create collection
You can create collections using the Appwrite Console or a [Server SDK](/docs/sdks#server).
{% tabs %}
{% tabsitem #console title="Console" %}
@@ -225,7 +225,7 @@ You can also configure **permissions** in the `createCollection` method, learn m
{% /tabsitem %}
{% /tabs %}
## Permissions {% #permissions %}
# Permissions {% #permissions %}
Appwrite uses permissions to control data access.
For security, only users that are granted permissions can access a resource.
This helps prevent accidental data leaks by forcing you to make more concious decisions around permissions.
@@ -235,7 +235,7 @@ This means users can't create new documents or read, update, and delete existing
[Learn about configuring permissions](/docs/products/databases/permissions).
## Attributes {% #attributes %}
# Attributes {% #attributes %}
All documents in a collection follow the same structure.
Attributes are used to define the structure of your documents and help the Appwrite's API validate your users' input.
Add your first attribute by clicking the **Add attribute** button.
@@ -258,7 +258,7 @@ If an attribute must be populated in all documents, set it as `required`.
If not, you may optionally set a default value.
Additionally, decide if the attribute should be a single value or an array of values.
## Indexes {% #indexes %}
# Indexes {% #indexes %}
Databases use indexes to quickly locate data without having to search through every document for matches.
To ensure the best performance, Appwrite recommends an index for every attribute queried.

View File

@@ -7,13 +7,13 @@ Databases are the largest organizational unit in Appwrite.
Each database contains a group [collections](/docs/products/databases/collections).
In future versions, different databases may be backed by a different database technology of your choosing.
## Create a database in Console
# Create a database in Console
The easiest way to create a database using the Appwrite Console.
You can create a database by navigating to the **Databases** page and clicking **Create database**.
## Create a database using Server SDKs
# Create a database using Server SDKs
You can programmatically create databases using a [Server SDK](/docs/sdks#server). Appwrite [Server SDKs](/docs/sdks#server) require an [API key](/docs/advanced/platform/api-keys).
{% multicode %}

View File

@@ -6,7 +6,7 @@ description: Master document management with Appwrite Databases. Learn how to cr
Each piece of data or information in Appwrite Databases is a document.
Documents have a structure defined by the parent collection.
## Create documents {% #create-documents %}
# Create documents {% #create-documents %}
{% info title="Permissions required" %}
You must grant **create** permissions to users at the **collection level** before users can create documents.
[Learn more about permissions](#permissions)
@@ -128,7 +128,7 @@ mutation {
During testing, you might prefer to create documents in the Appwrite Console.
To do so, navigate to the **Documents** tab of your collection and click the **Add document** button.
## List documents {% #list-documents %}
# List documents {% #list-documents %}
{% info title="Permissions required" %}
You must grant **read** permissions to users at the **collection level** before users can read documents.
@@ -256,7 +256,7 @@ query {
```
{% /multicode %}
## Permissions {% #permissions %}
# Permissions {% #permissions %}
In Appwrite, permissions can be granted at the collection level and the document level.
Before a user can create a document, you need to grant create permissions to the user.

View File

@@ -7,7 +7,7 @@ description: Understand how to do data ordering in Appwrite Databases. Learn how
You can order results returned by Appwrite Databases by using an order query.
For best performance, create an [index](/docs/products/databases/collections#indexes) on the column you plan to order by.
## Ordering one column {% #one-column %}
# Ordering one column {% #one-column %}
When querying using the [listDocuments](/docs/references/cloud/client-web/databases#listDocuments) endpoint,
you can specify the order of the documents returned using the `Query.orderAsc()` and `Query.orderDesc()` query methods.
@@ -124,7 +124,7 @@ query {
{% /multicode %}
## Multiple columns {% #multiple-columns %}
# Multiple columns {% #multiple-columns %}
To sort based on multiple attributes, simply provide multiple query methods.
For better performance, create an index on the first attribute that you order by.

View File

@@ -10,7 +10,7 @@ Pagination improves performance by returning a subset of results that match a qu
By default, list operations return 25 items per page, which can be changed using the `Query.limit(25)` operator.
Beware that **large pages can degrade performance**.
## Offset pagination {% #offset-pagination %}
# Offset pagination {% #offset-pagination %}
Offset pagination works by dividing documents into `M` pages containing `N` documents.
Every page is retrieved by skipping `offset = M * (N - 1)` items and reading the following `M` pages.
@@ -148,7 +148,7 @@ The request gets slower as the number of records increases because the database
If the data changes frequently, offset pagination will also produce **missing and duplicate** results.
{% /info %}
## Cursor pagination {% #cursor-pagination %}
# Cursor pagination {% #cursor-pagination %}
The cursor is a unique identifier for a document that points to where the next page should start.
After reading a page of documents, pass the last document's ID into the `Query.cursorAfter(lastId)` query method to get the next page of documents.
@@ -286,7 +286,7 @@ func main() async throws {
{% /multicode %}
## When to use what? {% #when-to-use %}
# When to use what? {% #when-to-use %}
Offset pagination should be used for collections that rarely change.
Offset paginations allow you to create indicator of the current page number and total page number.
For example, a list with up to 20 pages or static data like a list of countries or currencies.

View File

@@ -11,7 +11,7 @@ In Appwrite, permissions are **granted**, meaning a user has no access by defaul
A user with access granted at either collection level or document level will be able to access a document.
Users **don't need access at both levels** to access documents.
## Collection level {% #collection-level %}
# Collection level {% #collection-level %}
Collection level permissions apply to every document in the collection.
If a user has read, create, update, or delete permissions at the collection level, the user can access **all documents** inside the collection.
@@ -19,7 +19,7 @@ Configure collection level permissions by navigating to **Your collection** > **
[Learn more about permissions and roles](/docs/advanced/platform/permissions)
## Document level {% #document-level %}
# Document level {% #document-level %}
Document level permissions grant access to individual documents.
If a user has read, create, update, or delete permissions at the document level, the user can access the **individual document**.

View File

@@ -6,7 +6,7 @@ description: Harness the power of querying with Appwrite Databases. Discover var
Many list endpoints in Appwrite allow you to filter, sort, and paginate results using queries. Appwrite provides a common set of syntax to build queries.
## Query Class {% #query-class %}
# Query Class {% #query-class %}
Appwrite SDKs provide a `Query` class to help you build queries. The `Query` class has a method for each type of supported query.
@@ -33,7 +33,7 @@ Appwrite SDKs provide a `Query` class to help you build queries. The `Query` cla
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
## Building Queries {% #building-queries %}
# Building Queries {% #building-queries %}
Queries are passed to an endpoint through the `queries` parameter as an array of query strings, which can be generated using the `Query` class.

View File

@@ -13,25 +13,25 @@ These types of association between entities can be modeled in Appwrite using rel
Appwrite Relationships is an experimental feature. The API and behavior are subject to change in future versions.
{% /info %}
## Relationship Attributes {% #relationship-attributes %}
# Relationship Attributes {% #relationship-attributes %}
Relationships are represented in a collection using **relationship attributes**.
The relationship attribute contains the ID of related documents, which it references during read, update, and delete operations.
This attribute is **null** if a document has no related documents.
## When to use a relationship {% #when-to-use-relationships %}
# When to use a relationship {% #when-to-use-relationships %}
Relationships help reduce redundant information. For example, a user can create many posts in your app. You can model this without relationships by keeping a copy of the user's information in all the documents representing posts, but this creates a lot of duplicate information in your database about the user.
## Benefits of relationships {% #benefit-of-relationships %}
# Benefits of relationships {% #benefit-of-relationships %}
Duplicated records waste storage, but more importantly, makes the database much harder to maintain. If the user changes their user name, you will have to update dozens or hundreds of records, a problem commonly known as an update anomaly in databases. You can avoid duplicate information by storing users and posts in separate collections and relating a user and their posts through a relationship.
## Tradeoff {% #trade-offs %}
# Tradeoff {% #trade-offs %}
Consider using relationships when the same information is found in multiple places to avoid duplicates. However, relationships come with the tradeoff of slowing down queries. For applications where the best read and write performance is important, it may be acceptable to tolerate duplicate data.
## Directionality {% #directionality %}
# Directionality {% #directionality %}
Appwrite relationships can be one-way or two-way.
@@ -40,7 +40,7 @@ Appwrite relationships can be one-way or two-way.
| One-way | The relationship is only visible to one side of the relation. This is similar to a tree data structure. |
| Two-way | The relationship is visible to both sides of the relationship. This is similar to a graph data structure. |
## Types {% #types %}
# Types {% #types %}
Appwrite provides four different relationship types to enforce different associative rules between documents.
@@ -52,7 +52,7 @@ Appwrite provides four different relationship types to enforce different associa
| Many-to-many| A document can be related to many other documents. |
## On-delete {% #on-delete %}
# On-delete {% #on-delete %}
Appwrite also allows you to define the behavior of a relationship when a document is deleted.
@@ -62,7 +62,7 @@ Appwrite also allows you to define the behavior of a relationship when a documen
| Cascade | If a document has related documents, when it is deleted, the related documents are also deleted.|
| Set null | If a document has related documents, when it is deleted, the related documents are kept with their relationship attribute set to null.|
## Creating relationships {% #create-relationships %}
# Creating relationships {% #create-relationships %}
You can define relationships in the Appwrite Console, or using a [Server SDK](/docs/sdks#server)
{% tabs %}
@@ -290,7 +290,7 @@ await databases.CreateRelationshipAttribute(
{% /tabsitem %}
{% /tabs %}
## Creating documents {% #create-documents %}
# Creating documents {% #create-documents %}
If a collection has relationship attributes, you can create documents in two ways.
You create both parent and child at the same time using a **nested** syntax or link parent and child documents through **references***.
@@ -398,7 +398,7 @@ databases.createDocument(
```
{% /multicode %}
### Edge case behaviors
## Edge case behaviors
- If a nested child document is included and **no child document ID** is provided, the child document will be given a unique ID.
- If a nested child document is included and **no conflicting child document ID** exists, the child document will be **created**.
- If a nested child document is included and the **child document ID already exists**, the child document will be **updated**.
@@ -509,10 +509,10 @@ databases.createDocument(
{% /tabsitem %}
{% /tabs %}
## Queries {% #queries %}
# Queries {% #queries %}
Queries are currently not available in the experimental version of Appwrite Relationships but will be added in a later version.
## Update Relationships {% #update %}
# Update Relationships {% #update %}
Relationships can be updated by updating the relationship attribute.
{% multicode %}
@@ -615,8 +615,8 @@ databases.updateDocument(
{% /multicode %}
## Delete relationships {% #delete %}
### Unlink relationships, retain documents {% #unlink %}
# Delete relationships {% #delete %}
## Unlink relationships, retain documents {% #unlink %}
If you need to unlink documents in a relationship but retain the documents, you can do this by **updating the relationship attribute** and removing the ID of the related document.
@@ -624,7 +624,7 @@ If a document can be related to **only one document**, you can delete the relati
If a document can be related to **more than one document**, you can delete the relationship by setting the relationship attribute to an empty list.
### Delete relationships and documents {% #delete-both %}
## Delete relationships and documents {% #delete-both %}
If you need to delete the documents as well as unlink the relationship, the approach depends on the [on-delete behavior](#on-delete) of a relationship.
@@ -704,7 +704,7 @@ databases.deleteDocument(
Certainly, here is the content with the headings modified to the requested format:
## Permissions {% #permissions %}
# Permissions {% #permissions %}
To access documents in a relationship, you must have permission to access both the parent and child documents.
@@ -830,7 +830,7 @@ databases.createDocument(
When creating, updating, or deleting in a relationship, you must have permission to access all documents referenced.
If the user does not have read permission to any document, an exception will be thrown.
## Limitations {% #limitations %}
# Limitations {% #limitations %}
Relationships can be nested between collections, but are restricted to a **max depth of three levels**.
Relationship attribute key, type, and directionality can't be updated.

View File

@@ -9,7 +9,7 @@ Appwrite Functions are user-defined functions that can start small and scale big
These Functions can be triggered by HTTP requests, SDK methods, server events, webhooks, and scheduled executions.
Each function will have its own URL, execute in its own isolated container, and have its own configurable environment variables and permissions.
## Getting started {% #getting-started %}
# Getting started {% #getting-started %}
Appwrite Functions let you build anything you can imagine, but this flexibility makes it difficult to know where to start.
Start exploring by cloning one of the quick start templates or using a template with pre-built integration to quickly implement features.

View File

@@ -8,13 +8,13 @@ Appwrite Functions are mini-applications in Appwrite with their own endpoints. E
Functions can be created and deployed in different ways to meet your unique development habits. You can automatically deploy Appwrite Functions from source control, build your own deployment pipelines using the Appwrite CLI, or upload code files manually. Here's everything you need to know to deploy your first Appwrite Function.
## Git {% #git %}
# Git {% #git %}
The recommended way to manage your Appwrite Function deployments is to use a version control system, like Git. This offers simple versioning and collaboration that will easily fit into the rest of your development workflow.
![](https://appwrite.io/images-ee/docs/functions-starter-dark.png)
### Create function {% #create-function %}
## Create function {% #create-function %}
Before deploying your function with Git, create a new function attached to your Git repo.
@@ -29,14 +29,14 @@ Before deploying your function with Git, create a new function attached to your
9. If you have build steps, like installing dependencies, input the commands into the **Build settings** heading's **Command** field. For example, `npm install && npm build`.
10. Finally, configure the execute permissions of the function.
### Deploy {% #deploy %}
## Deploy {% #deploy %}
1. Using Git, checkout the branch you configured as the production branch when creating the Appwrite Function.
2. Create a new commit.
3. Push your new commit.
4. A new deployment will be automatically created, built and activated.
## CLI {% #cli %}
# CLI {% #cli %}
{% info title="CLI setup" %}
Before you can deploy with the Appwrite CLI, make sure you've [installed and initialized](/docs/tooling/command-line/installation) the CLI.
@@ -54,11 +54,11 @@ Edit the generated code, add dependencies, and deploy the function using the fol
appwrite deploy function
```
### Overwrite warning {% #overwrite-warning %}
## Overwrite warning {% #overwrite-warning %}
If you made changes in the Appwrite Console that are different from your `appwrite.json`, using the CLI deploy command will overwrite your console changes. Update your `appwrite.json` manually before deploying.
## Manual Deployment {% #manual %}
# Manual Deployment {% #manual %}
You can upload your functions to be deployed using the Appwrite Console. The example below shows a simple Node.js function.
@@ -93,7 +93,7 @@ Next, navigate to your Appwrite Console and upload the function.
6. Select **Activate deployment after build**.
7. Click **Create**.
## Domains {% #domains %}
# Domains {% #domains %}
Each deployed function can have its own domain. By default, one is generated for each of your functions.
@@ -108,7 +108,7 @@ To find or add a domain:
DNS records can take up to 48 hours to propagate.
## Debugging Build {% #debugging %}
# Debugging Build {% #debugging %}
After deploying a function, you can find the status and build logs in the Appwrite Console.
@@ -117,7 +117,7 @@ After deploying a function, you can find the status and build logs in the Appwri
3. Under the **Deployments** tab, find the status of the current and previous deployments.
4. Access build logs by clicking the **Build logs** button.
## Redeploy Builds {% #redeploy %}
# Redeploy Builds {% #redeploy %}
After updating the configuration, redeploy your function for changes to take effect. You can also redeploy to retry failed builds.

View File

@@ -7,7 +7,7 @@ description: Master serverless function development with Appwrite. Learn how to
Appwrite Functions offer a familiar interface if you've developed REST endpoints.
Each function is handled following a request and response pattern.
## Lifecycle {% #life-cycle %}
# Lifecycle {% #life-cycle %}
There is a clear lifecycle for all Appwrite Functions, from beginning to end.
Here's everything that happens during a function execution.
@@ -409,7 +409,7 @@ public class Handler {
If you prefer to learn through more examples like this, explore the [examples page](/docs/products/functions/examples).
## Context object {% #context-object %}
# Context object {% #context-object %}
Context is an object passed into every function to handle communication to both the end users, and logging to the Appwrite Console.
All input, output, and logging **must be handled through the context object** passed in.
@@ -422,7 +422,7 @@ You'll find these properties in the context object.
| log() | Method to log information to the Appwrite Console, end users will not be able to see these logs. See full examples [in the logging section](#logging). |
| error() | Methoc to log errors to the Appwrite Console, end users will not be able to see these errors. See full examples [in the logging section](#logging). |
#### Destructuring assignment {% #destructuring %}
### Destructuring assignment {% #destructuring %}
Some languages, namely JavaScript, support destructuring.
You'll see us use destructuring in examples, which has the following syntax.
@@ -456,7 +456,7 @@ export default async function ({ req, res, log, error }: any) {
```
{% /multicode %}
### Request {% #request %}
## Request {% #request %}
If you pass data into an Appwrite Function, it'll be found in the request object.
This includes all invocation inputs from Appwrite SDKs, HTTP calls, Appwrite events, or browsers visiting the configured domain.
@@ -671,7 +671,7 @@ public class Main {
```
{% /multicode %}
#### Headers {% #headers %}
### Headers {% #headers %}
Appwrite Functions will always receive a set of headers that provide meta data about the function execution.
These are provided alongside any custom headers sent to the function.
@@ -686,7 +686,7 @@ These are provided alongside any custom headers sent to the function.
| `x-appwrite-continent-code` | Displays the continent code of the configured locale. |
| `x-appwrite-continent-eu` | Describes if the configured local is within the EU. |
### Response {% #response %}
## Response {% #response %}
If you need to send a response to the invoker of the function, such as a user, client app, or an integration, use the response object.
The response information **will not be logged** to the Appwrite Console.
There are several possible ways to send a response, explore them in the following Appwrite Function.
@@ -936,7 +936,7 @@ To get the different response types, set one of the following query parameters i
| `html` | `/?type=html` | `https://64d4d22db370ae41a32e.appwrite.global/?type=html` |
| `empty` | `/` | `https://64d4d22db370ae41a32e.appwrite.global/` |
### Logging {% #logging %}
## Logging {% #logging %}
To protect user privacy, the request and response objects are not logged to the Appwrite Console by default.
This means, to see logs or debug function executions you need to use the `log()` and `error()` methods.
These logs are only visible to developers with access to the Appwrite Console.
@@ -1086,7 +1086,7 @@ You can access these logs through the following steps.
3. Under the Executions tab, click on an execution.
4. In the Response section, you'll be able to view logs under the Logs and Errors tabs.
## Accessing environment variables {% #environment-variables %}
# Accessing environment variables {% #environment-variables %}
If you need to pass constants or secrets to Appwrite Functions, you can use environment variables.
Environmental variables can be global, or function-specific.
@@ -1103,7 +1103,7 @@ If your function is using an Appwrite SDK with an API key, this API key needs to
| `APPWRITE_FUNCTION_RUNTIME_NAME` | The runtime of the running function. |
| `APPWRITE_FUNCTION_RUNTIME_VERSION` | The runtime version of the running function. |
### Function-level environment variables {% #function-variables %}
## Function-level environment variables {% #function-variables %}
Function-level environment variables will only be accessible in the function they belong to.
Function-level environment variables will override project-level variables when they have conflicting names.
@@ -1112,7 +1112,7 @@ Function-level environment variables will override project-level variables when
3. Under the **Settings** tab, navigate to **Environment variables**.
4. Create an environment variable by clicking **Create variable**, using the **Editor**, or import new variables through a `.env` file.
### Project-level variables {% #project-variables %}
## Project-level variables {% #project-variables %}
Project-level variables are accessible to all Appwrite Functions in your project.
Function-level environment variables will override project-level variables when they have conflicting names.
@@ -1214,7 +1214,7 @@ namespace runtime {
```
{% /multicode %}
## Dependencies {% #dependencies %}
# Dependencies {% #dependencies %}
Your function's dependencies should be managed by the package manager of each language.
By default, we include the following package managers in each runtime.
@@ -1294,14 +1294,14 @@ By default, we include the following package managers in each runtime.
To install your dependencies before your function is built, you should add the relevant install command to the top your function's **Build setting** > **Commands**.
## Using Appwrite in a function {% #using-appwrite %}
# Using Appwrite in a function {% #using-appwrite %}
Appwrite can be used in your functions by adding the relevant SDK to your function's dependencies.
Authenticating with Appwrite is done via an API key or a JWT token.
API keys must be generated and exported as an [environment variable](/docs/advanced/self-hosting/environment-variables).
You can read more about authentication in the [JWT login](/docs/products/auth/jwt) section of the docs.
### Using with API key {% #using-api-key %}
## Using with API key {% #using-api-key %}
API keys have defined scopes when you create them.
They ignore permissions and operate without a sessions.
Use API keys if the function should act as an admin type role, instead of acting on behalf of a user.
@@ -1612,7 +1612,7 @@ public class Main {
```
{% /multicode %}
### Using with JWT {% #using-jwt %}
## Using with JWT {% #using-jwt %}
JWTs allow you to act on behalf of an user in your Appwrite Function.
When using JWTs, you will be able to access and change **only** the resources with the same permissions as the user account that signed the JWT.
This preserves the permissions you configured on each resource.

View File

@@ -11,7 +11,7 @@ Appwrite Functions is all about flexibility. Behind the simple workflow hides so
Here's a currency conversion API that converts from Euros and Indian Rupees to US Dollars. We'll use an external API to get the latest exchange rates and query it using a dependency specific to each runtime.
### Prerequisites
## Prerequisites
{% tabs %}
{% tabsitem #node title="Node.js" %}
@@ -104,7 +104,7 @@ Finally, add `bundle install` to your function's build commands in the Appwrite
{% /tabs %}
### Code
## Code
{% multicode %}
```js
import { fetch } from 'undici';
@@ -236,7 +236,7 @@ end
Here's a simple voting system that allows users to vote on various topics. Appwrite Functions and the server SDK are used to enforce voting rules and prevent multiple votes from the same user for a single topic.
### Prerequisites
## Prerequisites
Create a Topics collection with the following attributes:
@@ -254,7 +254,7 @@ Create a Votes collection with the following attributes:
| `vote` | string | The vote cast by the user. Must be either "yes" or "no" |
### Code
## Code
{% multicode %}
```js
import { Client, Databases, Query } from 'node-appwrite';
@@ -498,7 +498,7 @@ For example, `<YOUR_FUNCTION_URL>/?userId=<USER_ID>&topicId=<TOPIC_ID>&vote=yes`
Here's a simple form page that handles form submissions, and can be used to store a user's message in a collection.
The form is submitted to the function using the `POST` method and the form data is sent as a URL-encoded string in the request body.
### Prerequisites
## Prerequisites
Create a Messages collection with the following attributes:
| Name | Type | Description |
@@ -507,7 +507,7 @@ Create a Messages collection with the following attributes:
| `email` | string | The email of the message author |
| `content` | string | The content of the message |
### Code
## Code
{% multicode %}

View File

@@ -5,7 +5,7 @@ description: Get started quickly with Appwrite Functions. Follow a step-by-step
---
You can create and execute your first Appwrite Function in minutes.
### Create function {% #create-function %}
# Create function {% #create-function %}
Before deploying your function with Git, create a new function attached to your Git repository.
@@ -26,7 +26,7 @@ Before deploying your function with Git, create a new function attached to your
You can find the code used by the starter template in your newly created Git repository.
Each push to your Git repo will trigger a new deployment.
### Execute {% #execute %}
## Execute {% #execute %}
You can execute your Appwrite Function through [many different triggers](/docs/products/functions/execution).
The easiest way to execute your first function is to use the Appwrite Console.
@@ -43,7 +43,7 @@ The easiest way to execute your first function is to use the Appwrite Console.
1. Wait for the execution to be marked **completed** and click to view the execution logs.
## Explore
# Explore
Use this your first function as a springboard to explore the flexible and powerful features of Appwrite Functions.
| Explore | |

View File

@@ -6,7 +6,7 @@ description: Choose the right runtime environment for your serverless functions
Appwrite Functions supports an extensive list of runtimes to meet your unique tech preferences. Not all runtimes are available on Appwrite Cloud yet. Check the [Cloud Support](#cloud-support) list to know which ones are available on Appwrite Cloud.
## Available runtimes {% #available-runtimes %}
# Available runtimes {% #available-runtimes %}
Below is a list of available Functions runtimes. The Appwrite team continually adds support for new runtimes.
{% table %}
@@ -114,7 +114,7 @@ Below is a list of available Functions runtimes. The Appwrite team continually a
---
{% /table %}
## Cloud support {% #cloud-support %}
# Cloud support {% #cloud-support %}
While still in beta, Appwrite Cloud has limited support for Cloud runtimes. As we continue to improve our Cloud offering, we will add support for more runtimes. Until then, these are the runtimes that you can use on Appwrite Cloud:

View File

@@ -12,7 +12,7 @@ It provides APIs to upload, download, delete, and list files, with many added ut
Appwrite Storage stores files like images, PDFs or videos. If you need to store data like profiles, recipes, or transactions, use [Appwrite Databases](/docs/products/databases).
{% /info %}
## Get started {% #get-started %}
# Get started {% #get-started %}
Get started with Appwrite Storage. Learn to setup up a bucket, upload, and download your first file.
[Quick start {% icon icon="cheveron-right" /%}](/docs/products/storage/quick-start)

View File

@@ -7,7 +7,7 @@ description: Organize and manage your files effectively with Appwrite Storage Bu
Storage buckets are a group of files, similar to collections in Appwrite Databases.
Buckets let you limit file size and extensions, whether or not to encrypt the files, and more.
## Create Bucket
# Create Bucket
You can create your bucket from the Appwrite Console or a [Server SDK](/docs/sdks#server).
{% tabs %}
@@ -221,7 +221,7 @@ You can also configure permission, file size and extension restrictions, and mor
{% /tabsitem %}
{% /tabs %}
## Permissions {% #permissions %}
# Permissions {% #permissions %}
Appwrite uses permissions to control file access.
For security, only users that are granted permissions can access a file.
This helps prevent accidental data leaks by forcing you to make more concious decisions around permissions.
@@ -231,21 +231,21 @@ This means users can't create new files or read, update, and delete existing fil
[Learn about configuring permissions](/docs/products/storage/permissions).
## Encrption {% #encryption %}
# Encrption {% #encryption %}
Appwrite provides added security settings for your buckets. Enable encryption under your bucket's **Settings** > **Security settings**.
You can enable encryption to encrypt files in your buckets. If your files are leaked, encrypted files cannot be read by the malicious actor.
Files bigger than 20MB cannot be encrypted.
## Compression {% #compression %}
# Compression {% #compression %}
Appwrite allows you to compress your files.
Two algorithms are available, which are [gzip](https://www.gzip.org/) and [zstd](https://github.com/facebook/zstd).
You can enable compress under your bucket's **Settings** > **Compression**.
For files larger than 20MB, compression will be skipped even when enabled.
## Maximum file size {% #max-size %}
# Maximum file size {% #max-size %}
Limit the maximum file size allowed in the bucket to prevent abuse.
You can configure maximum file size under your bucket's **Settings** > **Maximum file size**.
## File extensions {% #extensions %}
# File extensions {% #extensions %}
Limit the file extensions allowed in the bucket to prevent abuse. A maximum of 100 file extensions can be added. Leave blank to allow all file types.
You can configure maximum file size under your bucket's **Settings** > **File extensions**.

View File

@@ -36,7 +36,7 @@ Below you can find all the different parameters offered by the preview endpoint
| background | Set a background-color. Accepts any valid hex color value without the leading `#`. Only works with output formats supporting alpha channels like `png`. |
| output | Set the output image format. If not provided, will use the original image's format. Supported formats are: `jpg`, `jpeg`, `png`, `gif`, and `webp` |
## Examples {% #examples %}
# Examples {% #examples %}
Here are some examples using [Client SDKs](/docs/sdks#client).
{% multicode %}
```js

View File

@@ -11,7 +11,7 @@ In Appwrite, permissions are **granted**, meaning a user has no access by defaul
A user with access granted at either bucket level or file level will be able to access a file.
Users **don't need access at both levels** to access files.
## Bucket level {% #bucket-level %}
# Bucket level {% #bucket-level %}
Bucket level permissions apply to every file in the bucket.
If a user has read, create, update, or delete permissions at the bucket level, the user can access **all files** inside the bucket.
@@ -19,7 +19,7 @@ Configure bucket level permissions by navigating to **Your bucket** > **Settings
[Learn more about permissions and roles](/docs/advanced/platform/permissions)
## File level {% #file-level %}
# File level {% #file-level %}
File level permissions grant access to individual files.
If a user has read, create, update, or delete permissions at the file level, the user can access the **individual file**.

View File

@@ -8,13 +8,13 @@ readtime: 5
You can create your first bucket, upload, and download your first file in minutes.
## Create bucket {% #create-bucket %}
# Create bucket {% #create-bucket %}
You can create a bucket in the Appwrite Console by navigating to **Storage** > **Create bucket**.
In your bucket, navigate to **Settings** > **Permissions**, then add a new **Any** role with **CREATE** and **READ** permissions.
This allows anyone to create and read files in this bucket.
## Create file {% #create-file %}
# Create file {% #create-file %}
To upload a file, add this to you web, Flutter, Apple, or Android app.
@@ -127,7 +127,7 @@ During testing, you might prefer to create documents in the Appwrite Console.
To do so, navigate to the **Documents** tab of your collection and click the **Add document** button.
## Download file {% #download-file %}
# Download file {% #download-file %}
To download a file, use the `getFileDownload` method.
{% multicode %}

View File

@@ -6,7 +6,7 @@ description: Effortlessly upload and download files with Appwrite Storage. Learn
You can upload and download files both programmatically using SDKs or through the Appwrite Console.
## Create file {% #create-file %}
# Create file {% #create-file %}
After you create a bucket or have navigated to bucket details, you can access the **Files** tab so you can upload, view, delete and update files in the bucket using the Appwrite project's dashboard. You can also perform all those operations from Appwrite's client SDK, server SDKs, and REST APIs as long as you have the proper permission.
@@ -122,15 +122,15 @@ You can also upload files programmatically using our SDKs:
During testing, you might prefer to create documents in the Appwrite Console.
To do so, navigate to the **Documents** tab of your collection and click the **Add document** button.
## Large files {% #large-files %}
# Large files {% #large-files %}
When you are trying to upload any files above 5MB, you will need to upload them in chunks for better reliability and performance.
If you're using an Appwrite SDK, this is handled automatically.
If you're not using an SDK, you can [learn more about REST API file handling](/docs/apis/rest#files).
## InputFile {% #input-file %}
# InputFile {% #input-file %}
Every language and platform handles file inputs differently. This section documents the expected input type of each SDK. Where applicable, Appwrite provides an `InputFile` class to accept multiple file sources, like paths, buffers, streams, or plain text.
## Client SDKs
# Client SDKs
{% tabs %}
{% tabsitem #web title="Web" %}
@@ -180,7 +180,7 @@ The Appwrite Apple SDK expects an `InputFile` class for file inputs.
{% /tabsitem %}
{% /tabs %}
## Server SDK
# Server SDK
{% tabs %}
{% tabsitem #nodejs title="Node.js" %}
@@ -275,7 +275,7 @@ The Appwrite .NET SDK expects an `InputFile` class for file inputs.
{% /tabsitem %}
{% /tabs %}
## Get file {% #get-file %}
# Get file {% #get-file %}
To get a metadata about a.file, use the `getFile` method.
{% multicode %}
@@ -384,7 +384,7 @@ class MainActivity : AppCompatActivity() {
```
{% /multicode %}
## Download file {% #download-file %}
# Download file {% #download-file %}
To download a file, use the `getFileDownload` method.
{% multicode %}
@@ -489,7 +489,7 @@ class MainActivity : AppCompatActivity() {
```
{% /multicode %}
## Get File {% #get-file %}
# Get File {% #get-file %}
To get a file, use the `getFile` method.
{% multicode %}
@@ -598,7 +598,7 @@ class MainActivity : AppCompatActivity() {
```
{% /multicode %}
## Get File Preview {% #get-file-preview %}
# Get File Preview {% #get-file-preview %}
To get a file preview image , use the `getFilePreview` method.
{% multicode %}
@@ -703,7 +703,7 @@ class MainActivity : AppCompatActivity() {
```
{% /multicode %}
## View File {% #view-file%}
# View File {% #view-file%}
To view a file, use the `getFileView` method.

View File

@@ -108,11 +108,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -75,11 +75,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -8,7 +8,7 @@ Appwrite provides SDK libraries for major programming languages and platforms so
We're always working on improving and extending the current stack of available platforms and SDKs, listed below is a list of official libraries the Appwrite team is maintaining.
## Client {% #client %}
# Client {% #client %}
Client libraries for integrating with Appwrite to build client-based applications and websites. Read one of the many [quick starts](/docs/quick-starts) guides for your framework of choice to start building your first application.
@@ -43,7 +43,7 @@ Client libraries for integrating with Appwrite to build client-based application
*
{% /table %}
## Server {% #server %}
# Server {% #server %}
Server libraries for integrating with Appwrite to build server side integrations or use inside your [Appwrite Functions](/docs/products/functions). Read one of the many [quick starts](/docs/quick-starts) guides for your language/runtime of choice to start building your first server integration.
@@ -110,7 +110,7 @@ Server libraries for integrating with Appwrite to build server side integrations
If you would like to help us extend our platforms and SDKs stack, you are more than welcome to contact us or check out our Appwrite SDK Generator project GitHub repository and read our contribution guide.
## Protocols {% #protocols %}
# Protocols {% #protocols %}
We are always looking to add new SDKs to our platform. If the SDK you are looking for is still missing, labeled as beta or experimental, or you simply do not want to integrate with an SDK, you can always integrate with Appwrite directly using any standard HTTP, GraphQL, or WebSocket clients and the relevant Appwrite protocol.
Appwrite supports multiple API protocols for maximum flexibility and developer convenience. You can learn more about how to integrate directly with them using one of the following available guides:
@@ -121,7 +121,7 @@ Appwrite supports multiple API protocols for maximum flexibility and developer c
[Integrate with the Appwrite GraphQL API {% icon icon="cheveron-right" /%}](/docs/apis/graphql)
## Community {% #community %}
# Community {% #community %}
If you have created your own framework or any other technology specific integration and would like us to list it here please [contact us](/contact-us).
If you would like to help us extend the Appwrite SDKs stack, you are more than welcome to check out the Appwrite [SDK Generator](https://github.com/appwrite/sdk-generator) project on GitHub and read our [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md).

View File

@@ -10,11 +10,11 @@ The **Appwrite Assistant** is an AI-powered tool engineered to augment Appwrite-
While the Appwrite Assistant remains under active development and is considered experimental, it undergoes incremental refinement. Its proficiency in comprehending user queries and delivering relevant responses improves with sustained usage.
{% /info %}
## Getting started {% #getting-started %}
# Getting started {% #getting-started %}
To engage the Appwrite Assistant, access the Command Center within your Appwrite Console, and proceed to the `Ask the AI` tab in the navigation.
## Querying {% #querying %}
# Querying {% #querying %}
The Appwrite Assistant accommodates queries related to Appwrite, encompassing topics such as:
@@ -23,7 +23,7 @@ The Appwrite Assistant accommodates queries related to Appwrite, encompassing to
- How can I create a user account?
- How to store a file in a bucket?
## Optimizations {% #optimizations %}
# Optimizations {% #optimizations %}
For optimal utilization of the Appwrite Assistant, consider the following recommendations:
@@ -32,6 +32,6 @@ For optimal utilization of the Appwrite Assistant, consider the following recomm
- **Query Refinement**: In cases of misinterpretation, rephrase queries.
- **Manual Documentation Search**: In scenarios where the Assistant falls short, manually search the Appwrite documentation.
## Privacy {% #privacy %}
# Privacy {% #privacy %}
When you use the Appwrite Assistant, your questions are sent to OpenAI to generate a response. OpenAI may collect and store your questions and responses for the purposes of improving their services.

View File

@@ -12,7 +12,7 @@ Commands follows the following general syntax:
appwrite [COMMAND] --[OPTIONS]
```
## List {% #list %}
# List {% #list %}
Below is a list of the available commands in the Appwrite CLI. You can get more information on each command by running `appwrite [COMMAND] --help`.
@@ -65,16 +65,16 @@ Below is a list of the available commands in the Appwrite CLI. You can get more
{% /table %}
## Verbose {% #verbose %}
# Verbose {% #verbose %}
In case of errors with any command, you can get more information about what went wrong using the `--verbose` flag
```sh
appwrite users list --verbose
```
## Examples {% #examples %}
# Examples {% #examples %}
### Create user
## Create user
To create a new user in your project, you can use the create command.
@@ -84,7 +84,7 @@ appwrite users create --userId "unique()" \
--password very_strong_password
```
### List Users
## List Users
To get a list of all your project users, you can use the list command.
@@ -92,7 +92,7 @@ To get a list of all your project users, you can use the list command.
appwrite users list
```
### List collections
## List collections
To get a list of all your collections, you can use the listCollections command.
@@ -106,7 +106,7 @@ If you wish to parse the output from the CLI, you can request the CLI output in
appwrite databases listCollections --databaseId [DATABASE_ID]--json
```
### Get collection
## Get collection
To get more information on a particular collection, you can make use of the getCollection command and pass in the collectionId.
@@ -114,7 +114,7 @@ To get more information on a particular collection, you can make use of the getC
appwrite databases getCollection --databaseId [DATABASE_ID] --collectionId [COLLECTION_ID]
```
### Create document
## Create document
To create a new document in an existing collection, use the `createDocument` command.

View File

@@ -6,7 +6,7 @@ description: Efficiently deploy your Appwrite projects using the Command-Line To
The Apprite CLI allows you to create and deploy databases, collections, buckets, teams and functions to your Appwrite project from a configuration file. This is especially helpful if you're trying to track project setup using version control.
## Initialization {% #initialization %}
# Initialization {% #initialization %}
After you're logged in, the CLI needs to be initialized with your Appwrite project. You can initialize the CLI using:
@@ -28,7 +28,7 @@ You can fetch all the existing teams in your current project using:
appwrite init team
```
## Deploying Functions {% #deploying-function %}
# Deploying Functions {% #deploying-function %}
The CLI also handles the creation and deployment of Appwrite Functions. Run this command in the folder holding your `appwrite.json` file.
@@ -50,7 +50,7 @@ appwrite deploy function
✓ Success Deployed Awesome Function ( 621229798628cf5bf712 )
```
## Deploying Collections {% #deploying-collections %}
# Deploying Collections {% #deploying-collections %}
The Appwrite CLI also helps you deploy your project's databases and collections schema from one project to another.
@@ -62,7 +62,7 @@ The deploy command will overwrite existing collections causing existing data to
appwrite deploy collection
```
## Deploying Teams {% #deploying-teams %}
# Deploying Teams {% #deploying-teams %}
The Appwrite CLI can create teams to organize users. Teams can be used to grant access permissions to a group of users. Learn more about permissions.
@@ -72,7 +72,7 @@ Deploy teams by running this command in the folder holding your `appwrite.json`
appwrite deploy team
```
## Deploying Storage {% #deploying-storage %}
# Deploying Storage {% #deploying-storage %}
The Appwrite CLI allows you to configure and deploy buckets across projects. All the bucket's settings are available through the [appwrite.json](/docs/tooling/command-line/deployment#appwrite-json) file.
@@ -82,15 +82,15 @@ Deploy storage buckets by running this command in the folder holding your `appwr
appwrite deploy bucket
```
## Conflicts {% #conflicts %}
# Conflicts {% #conflicts %}
When using `appwrite.json`, changes made in the Appwrite Console can cause conflicts with the local config. To avoid conflicts, prefer updating configuration locally and deploying instead of using the Console.
## The appwrite.json file {% #appwrite-json %}
# The appwrite.json file {% #appwrite-json %}
An `appwrite.json` file is created by the CLI when you initialize your project. It stores all the configuration for the CLI to be able to interact with your Appwrite project in JSON format. When using the `appwrite deploy` command, the CLI uses information from `appwrite.json` to deploy your functions and collections.
### Configuration {% #configuration %}
## Configuration {% #configuration %}
Here's a complete list of all configurable options in `appwrite.json`:
@@ -104,7 +104,7 @@ Here's a complete list of all configurable options in `appwrite.json`:
| `teams` | array of teams | Configuration of teams in your project. |
| `buckets` | array of buckets | Configuration of teams in your project. |
#### Function options
### Function options
| Option | Type | Description |
| --- | --- | --- |
@@ -120,14 +120,14 @@ Here's a complete list of all configurable options in `appwrite.json`:
| `timeout` | int | Execution timeout of the function in seconds, with a maximum configurable limit of 900 seconds. |
| `variables` | JSON object | Variables provided to the function on execution stored as a key-value JSON object. |
#### Databases options
### Databases options
| Option | Type | Description |
| --- | --- | --- |
| `$id` | string | Database ID. |
| `name` | string | Database Name. |
#### Collection options
### Collection options
| Option | Type | Description |
| --- | --- | --- |
@@ -140,7 +140,7 @@ Here's a complete list of all configurable options in `appwrite.json`:
| `attributes` | array of objects | Defines a list of attributes in the collection. [Learn more about the Attributes List Object](/docs/references/cloud/models/attributeList). |
| `indexes` | array of objects | Defines a list of indexes in the collection. [Learn more about the Indexes List Object](/docs/references/cloud/models/indexList). |
#### Buckets options
### Buckets options
| Option | Type | Description |
| --- | --- | --- |
@@ -155,7 +155,7 @@ Here's a complete list of all configurable options in `appwrite.json`:
| `encryption` | boolean | Whether the bucket's content is encrypted. |
| `antivirus` | boolean | Whether virus scanning is enabled for the bucket's content. |
#### Teams options
### Teams options
| Option | Type | Description |
| --- | --- | --- |

View File

@@ -6,13 +6,13 @@ description: Get started with the Appwrite CLI by following the installation gui
The [Appwrite CLI](https://github.com/appwrite/sdk-for-cli) is a command-line application that allows you to interact with the [Appwrite server](https://appwrite.io/docs/getting-started-for-server) and perform server-side tasks using your terminal. This includes creating and managing projects, managing resources (documents, files, users), creating and deploying Appwrite Functions, and other operations available through Appwrite's API.
## Installation {% #Installation %}
# Installation {% #Installation %}
The CLI is packaged both as an [npm module](https://www.npmjs.com/package/appwrite-cli) as well as a [standalone binary](https://github.com/appwrite/sdk-for-cli/releases/latest) for your operating system, making it completely dependency free, platform independent and language agnostic.
If you plan to use the CLI to initialize new Appwrite Functions, ensure that [Git is installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) on your machine.
### Install with npm {% #install-with-npm %}
## Install with npm {% #install-with-npm %}
If you have npm set up, run the command below to install the CLI.
@@ -20,7 +20,7 @@ If you have npm set up, run the command below to install the CLI.
npm install -g appwrite-cli
```
### Install with script {% #install-with-script %}
## Install with script {% #install-with-script %}
For a completely dependency-free installation, the CLI also ships with a convenient installation script for your operating system
@@ -56,7 +56,7 @@ curl -sL https://appwrite.io/cli/install.sh | bash
{% /tabsitem %}
{% /tabs %}
### Verify installation {% #verify-installation %}
## Verify installation {% #verify-installation %}
After the installation is complete, you can verify the Appwrite CLI is available by checking its version number.
@@ -64,7 +64,7 @@ After the installation is complete, you can verify the Appwrite CLI is available
appwrite -v
```
## Get started {% #get-started %}
# Get started {% #get-started %}
Before you can use the CLI, you need to login to your Appwrite account using
@@ -87,7 +87,7 @@ appwrite client --selfSigned true
{% /info %}
### Next steps {% #next-steps %}
## Next steps {% #next-steps %}
You can use the CLI to create and deploy functions and collections. Deploy commands allow you to configure your Appwrite project programmatically and replicate functions and collection schemas across Appwrite projects.
@@ -101,7 +101,7 @@ You can choose to use the CLI in a headless and non-interactive mode without the
[Learn more about CI mode](/docs/tooling/command-line/non-interactive)
## Help {% #help %}
# Help {% #help %}
If you get stuck anywhere, you can always use the `help` command to get the usage examples.
@@ -109,7 +109,7 @@ If you get stuck anywhere, you can always use the `help` command to get the usag
appwrite help
```
## Configuration {% #configuration %}
# Configuration {% #configuration %}
At any point, if you would like to change your server's endpoint, project ID, or self-signed certificate acceptance, use the `client` command.
@@ -121,7 +121,7 @@ appwrite client --reset // Resets your CLI configuration
appwrite client --debug // Prints your current configuration
```
## Uninstall {% #uninstall %}
# Uninstall {% #uninstall %}
If you installed Appwrite CLI using NPM, you can use the following command to uninstall it.

View File

@@ -16,10 +16,10 @@ When you set the global configuration parameters using the `appwrite client` com
In this mode, the CLI can only interact with one project at a time.
## API Keys {% #api-keys %}
# API Keys {% #api-keys %}
In non-interactive mode, the CLI uses an API key to authenticate. Your API key must have sufficient permissions to execute the commands you plan to use. [Learn more about API Keys](/docs/advanced/platform/api-keys).
## Deployment {% #deployment %}
# Deployment {% #deployment %}
Appwrite's deploy commands can also be executed in a non-interactive mode. This applies to both function and collection deployment.
You can deploy a function non-interactively by using the `--yes` option to skip all warnings and specifying which functions you want to deploy.

View File

@@ -12,11 +12,11 @@
<!-- Titles -->
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:title" content={title} />
<!-- Desscription -->
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta name="twitter:description" content={description} />
<meta name="twitter:description" content={description} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />

View File

@@ -17,7 +17,7 @@ In this tutorial, you will build Idea tracker with Appwrite and React.
![Create project screen](/images/docs/tutorials/idea-tracker.png)
{% /only_light %}
## Concepts {% #concepts %}
# Concepts {% #concepts %}
This tutorial will introduce the following concepts:
@@ -28,7 +28,7 @@ This tutorial will introduce the following concepts:
5. Storage
## Prerequisites {% #prerequisites %}
# Prerequisites {% #prerequisites %}
1. Basic knowledge of JavaScript and React.
2. Have [Node.js](https://nodejs.org/en) and [NPM](https://www.npmjs.com/) installed on your computer

View File

@@ -5,7 +5,7 @@ description: Create a React app project and integrate with Appwrite.
step: 2
---
## Create React project {% #create-react-project %}
# Create React project {% #create-react-project %}
Create a React app with the `npm create` command.
@@ -13,7 +13,7 @@ Create a React app with the `npm create` command.
npm create vite@latest --template react ideas-tracker && cd ideas-tracker
```
## Add dependencies {% #add-dependencies %}
# Add dependencies {% #add-dependencies %}
Install the JavaScript Appwrite SDK.

View File

@@ -5,7 +5,7 @@ description: Import and initialize Appwrite for your react application.
step: 3
---
## Create project {% #create-project %}
# Create project {% #create-project %}
Head to the [Appwrite Console](https://cloud.appwrite.io/console).
@@ -29,7 +29,7 @@ Then, under **Add a platform**, add a **Web app**. The **Hostname** should be lo
You can skip optional steps.
## Initialize Appwrite SDK {% #init-sdk %}
# Initialize Appwrite SDK {% #init-sdk %}
To use Appwrite in our Svelte app, we'll need to find our project ID. Find your project's ID in the **Settings** page.

View File

@@ -5,7 +5,7 @@ description: Add authentication to your react application.
step: 4
---
## User context
# User context
In React, you can use [context](https://reactjs.org/docs/context.html) to share data between components.
We'll use context and a custom hook to manage our user's data.
@@ -63,7 +63,7 @@ export function UserProvider(props) {
Now, we can use the `useUser` hook to access the user's data from any component. However, we first need to wrap our app with the `UserProvider`.
## Basic routing
# Basic routing
First, wrap the `main` element with the `UserProvider` component.
@@ -112,7 +112,7 @@ function App() {
export default App;
```
## Home page
# Home page
Create a new file `src/pages/Home.jsx` and add the following stub code to it.
@@ -125,7 +125,7 @@ export function Home() {
}
```
## Login page
# Login page
Finally, we are able to create the login page. Users will be able to login or register from this page, so we'll need to add two buttons.

View File

@@ -4,7 +4,7 @@ title: Add database
description: Add a database to your React application using Appwrite Web SDK.
step: 6
---
## Create collection
# Create collection
In Appwrite, data is stored as a collection of documents. Create a collection in the [Appwrite Console](https://cloud.appwrite.io/) to store our ideas.
{% only_dark %}
@@ -21,7 +21,7 @@ Create a new collection with the following attributes:
| title | String | Yes |
| description | String | No |
## Ideas context
# Ideas context
Now that you have a collection to hold ideas, we can read and write to it from our app. Like we did with the user data, we will create a React context to hold our ideas.
Create a new file `src/lib/context/ideas.jsx` and add the following code to it.

Some files were not shown because too many files have changed in this diff Show More