Merge branch 'main' into tailwind-integration

This commit is contained in:
Jesse Winton
2024-08-05 19:01:02 -04:00
265 changed files with 7939 additions and 3348 deletions

View File

@@ -10,7 +10,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
ref: ${{ github.event.pull_request.merge_commit_sha }}
- name: Use Node.js
uses: actions/setup-node@v3
with:
@@ -34,6 +34,8 @@ jobs:
- name: Build Website
env:
NODE_OPTIONS: '--max_old_space_size=8192'
PUBLIC_APPWRITE_ENDPOINT: ${{ secrets.PUBLIC_APPWRITE_ENDPOINT }}
PUBLIC_APPWRITE_DASHBOARD: ${{ secrets.PUBLIC_APPWRITE_DASHBOARD }}
PUBLIC_APPWRITE_PROJECT_ID: ${{ secrets.PUBLIC_APPWRITE_PROJECT_ID }}
PUBLIC_APPWRITE_DB_MAIN_ID: ${{ secrets.PUBLIC_APPWRITE_DB_MAIN_ID }}
PUBLIC_APPWRITE_COL_THREADS_ID: ${{ secrets.PUBLIC_APPWRITE_COL_THREADS_ID }}

View File

@@ -54,9 +54,11 @@
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.13.1",
"dequal": "^2.0.3",
"embla-carousel": "^8.1.5",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-svelte": "^2.40.0",
"fuse.js": "^7.0.0",
"highlight.js": "^11.9.0",
"markdown-it": "^14.1.0",
"meilisearch": "^0.37.0",

85
pnpm-lock.yaml generated
View File

@@ -14,9 +14,18 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
embla-carousel-svelte:
specifier: ^8.1.8
version: 8.1.8(svelte@4.2.18)
embla-carousel-wheel-gestures:
specifier: ^8.0.1
version: 8.0.1(embla-carousel@8.1.5)
h3:
specifier: ^1.12.0
version: 1.12.0
remeda:
specifier: ^2.7.1
version: 2.7.1
tailwind-merge:
specifier: ^2.4.0
version: 2.4.0
@@ -81,6 +90,9 @@ importers:
dequal:
specifier: ^2.0.3
version: 2.0.3
embla-carousel:
specifier: ^8.1.5
version: 8.1.5
eslint:
specifier: ^8.57.0
version: 8.57.0
@@ -90,6 +102,9 @@ importers:
eslint-plugin-svelte:
specifier: ^2.40.0
version: 2.41.0(eslint@8.57.0)(svelte@4.2.18)
fuse.js:
specifier: ^7.0.0
version: 7.0.0
highlight.js:
specifier: ^11.9.0
version: 11.9.0
@@ -2174,6 +2189,28 @@ packages:
electron-to-chromium@1.4.812:
resolution: {integrity: sha512-7L8fC2Ey/b6SePDFKR2zHAy4mbdp1/38Yk5TsARO66W3hC5KEaeKMMHoxwtuH+jcu2AYLSn9QX04i95t6Fl1Hg==}
embla-carousel-reactive-utils@8.1.8:
resolution: {integrity: sha512-bwV/23WD3Ecm0YuQ4I6Syzs3tdVJw0Oj3VCZlEODv1kH8LZ5kNDLgX2Uvx5brvoe2hpifBHPBQ8gYlxNL5kMPA==}
peerDependencies:
embla-carousel: 8.1.8
embla-carousel-svelte@8.1.8:
resolution: {integrity: sha512-6tX0C+GJ4loCVV015zePPeONupTvus4ZuDWiAV4LHvlrVqtD/I1uEuWUurtYDoB6tuVS6f8e5aN9mY+a1CfGxw==}
peerDependencies:
svelte: ^3.49.0 || ^4.0.0
embla-carousel-wheel-gestures@8.0.1:
resolution: {integrity: sha512-LMAnruDqDmsjL6UoQD65aLotpmfO49Fsr3H0bMi7I+BH6jbv9OJiE61kN56daKsVtCQEt0SU1MrJslbhtgF3yQ==}
engines: {node: '>=10'}
peerDependencies:
embla-carousel: ^8.0.0 || ~8.0.0-rc03
embla-carousel@8.1.5:
resolution: {integrity: sha512-R6xTf7cNdR2UTNM6/yUPZlJFRmZSogMiRjJ5vXHO65II5MoUlrVYUAP0fHQei/py82Vf15lj+WI+QdhnzBxA2g==}
embla-carousel@8.1.8:
resolution: {integrity: sha512-KuHPA8qcAts6YE6ELtt38XYAb26hnKw8Ga0lSXmrhm1oI97t6oACFkqSsy33dfeZQEhaZB6VwWvaWQJRJVgSgA==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -2375,6 +2412,10 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
fuse.js@7.0.0:
resolution: {integrity: sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==}
engines: {node: '>=10'}
gauge@4.0.4:
resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@@ -3481,6 +3522,9 @@ packages:
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
remeda@2.7.1:
resolution: {integrity: sha512-P+tm5rsatmF0GRh/EWq7vfoVyYyZbjO5Un/d08rZyEiznQWHXTtxhPu8cTntlQ8bHyPJBF3n2i5yFFmgaS3stA==}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -3930,6 +3974,10 @@ packages:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
type-fest@4.23.0:
resolution: {integrity: sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==}
engines: {node: '>=16'}
typescript@5.5.2:
resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==}
engines: {node: '>=14.17'}
@@ -4079,6 +4127,10 @@ packages:
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
wheel-gestures@2.2.5:
resolution: {integrity: sha512-01BlXRjBVt5Gy0VH2rRqMeccHruTGq2Gd1fx0UqCPN8KDeDCmlTXsRGc/hXJk6W+wnO9CNJp2xfntMNRArBxKQ==}
engines: {node: '>=10'}
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
@@ -4192,7 +4244,7 @@ snapshots:
'@babel/code-frame@7.24.7':
dependencies:
'@babel/highlight': 7.24.7
picocolors: 1.0.0
picocolors: 1.0.1
'@babel/compat-data@7.24.7': {}
@@ -4289,7 +4341,7 @@ snapshots:
'@babel/helper-validator-identifier': 7.24.7
chalk: 2.4.2
js-tokens: 4.0.0
picocolors: 1.0.0
picocolors: 1.0.1
'@babel/parser@7.24.7':
dependencies:
@@ -6349,6 +6401,25 @@ snapshots:
electron-to-chromium@1.4.812: {}
embla-carousel-reactive-utils@8.1.8(embla-carousel@8.1.8):
dependencies:
embla-carousel: 8.1.8
embla-carousel-svelte@8.1.8(svelte@4.2.18):
dependencies:
embla-carousel: 8.1.8
embla-carousel-reactive-utils: 8.1.8(embla-carousel@8.1.8)
svelte: 4.2.18
embla-carousel-wheel-gestures@8.0.1(embla-carousel@8.1.5):
dependencies:
embla-carousel: 8.1.5
wheel-gestures: 2.2.5
embla-carousel@8.1.5: {}
embla-carousel@8.1.8: {}
emoji-regex@8.0.0: {}
emoji-regex@9.2.2: {}
@@ -6606,6 +6677,8 @@ snapshots:
function-bind@1.1.2: {}
fuse.js@7.0.0: {}
gauge@4.0.4:
dependencies:
aproba: 2.0.0
@@ -7656,6 +7729,10 @@ snapshots:
regenerator-runtime@0.14.1: {}
remeda@2.7.1:
dependencies:
type-fest: 4.23.0
require-directory@2.1.1: {}
require-in-the-middle@7.3.0:
@@ -8173,6 +8250,8 @@ snapshots:
type-fest@0.20.2: {}
type-fest@4.23.0: {}
typescript@5.5.2: {}
uc.micro@2.1.0: {}
@@ -8324,6 +8403,8 @@ snapshots:
tr46: 0.0.3
webidl-conversions: 3.0.1
wheel-gestures@2.2.5: {}
which@2.0.2:
dependencies:
isexe: 2.0.0

View File

@@ -0,0 +1 @@
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M12.467 11.058 C 12.375 11.089,12.180 11.176,12.033 11.252 C 11.646 11.454,4.391 18.744,4.191 19.133 C 3.977 19.550,3.974 20.303,4.186 20.735 C 4.293 20.953,5.393 22.094,8.150 24.846 C 11.945 28.635,11.969 28.657,12.359 28.769 C 12.842 28.908,13.335 28.876,13.737 28.680 C 13.954 28.575,16.126 26.443,21.866 20.702 L 29.699 12.868 28.966 12.129 C 28.531 11.691,28.101 11.322,27.908 11.223 C 27.463 10.994,26.981 10.953,26.491 11.101 C 26.102 11.219,26.069 11.251,18.211 19.093 L 10.322 26.967 11.189 25.233 L 12.056 23.500 10.278 21.716 L 8.501 19.933 10.717 17.717 L 12.933 15.501 14.700 17.267 L 16.467 19.033 17.783 17.716 L 19.099 16.400 16.566 13.866 C 14.733 12.032,13.950 11.293,13.733 11.191 C 13.410 11.039,12.740 10.968,12.467 11.058 M28.844 14.711 L 27.989 16.422 29.761 18.195 L 31.533 19.967 28.532 22.967 C 26.392 25.105,25.489 26.053,25.385 26.266 C 25.191 26.665,25.188 27.313,25.379 27.739 C 25.681 28.413,26.326 28.829,27.067 28.829 C 27.884 28.829,27.776 28.919,31.907 24.780 C 36.005 20.674,35.947 20.743,35.953 19.967 C 35.959 19.197,35.961 19.199,32.715 15.950 C 31.094 14.327,29.752 13.000,29.733 13.000 C 29.714 13.000,29.314 13.770,28.844 14.711 " stroke="none" fill-rule="evenodd" fill="black"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -14,37 +14,38 @@ $web-icon-chevron-up: "\ea0d";
$web-icon-close: "\ea0e";
$web-icon-command: "\ea0f";
$web-icon-copy: "\ea10";
$web-icon-dark: "\ea11";
$web-icon-discord: "\ea12";
$web-icon-divider-vertical: "\ea13";
$web-icon-download: "\ea14";
$web-icon-ext-link: "\ea15";
$web-icon-firebase: "\ea16";
$web-icon-github: "\ea17";
$web-icon-google: "\ea18";
$web-icon-hamburger-menu: "\ea19";
$web-icon-light: "\ea1a";
$web-icon-linkedin: "\ea1b";
$web-icon-location: "\ea1c";
$web-icon-logout-left: "\ea1d";
$web-icon-logout-right: "\ea1e";
$web-icon-mailgun: "\ea1f";
$web-icon-message: "\ea20";
$web-icon-microsoft: "\ea21";
$web-icon-minus: "\ea22";
$web-icon-nuxt: "\ea23";
$web-icon-platform: "\ea24";
$web-icon-play: "\ea25";
$web-icon-plus: "\ea26";
$web-icon-product-hunt: "\ea27";
$web-icon-refine: "\ea28";
$web-icon-rest: "\ea29";
$web-icon-search: "\ea2a";
$web-icon-sendgrid: "\ea2b";
$web-icon-star: "\ea2c";
$web-icon-system: "\ea2d";
$web-icon-textmagic: "\ea2e";
$web-icon-twitter: "\ea2f";
$web-icon-vue: "\ea30";
$web-icon-x: "\ea31";
$web-icon-youtube: "\ea32";
$web-icon-daily-dev: "\ea11";
$web-icon-dark: "\ea12";
$web-icon-discord: "\ea13";
$web-icon-divider-vertical: "\ea14";
$web-icon-download: "\ea15";
$web-icon-ext-link: "\ea16";
$web-icon-firebase: "\ea17";
$web-icon-github: "\ea18";
$web-icon-google: "\ea19";
$web-icon-hamburger-menu: "\ea1a";
$web-icon-light: "\ea1b";
$web-icon-linkedin: "\ea1c";
$web-icon-location: "\ea1d";
$web-icon-logout-left: "\ea1e";
$web-icon-logout-right: "\ea1f";
$web-icon-mailgun: "\ea20";
$web-icon-message: "\ea21";
$web-icon-microsoft: "\ea22";
$web-icon-minus: "\ea23";
$web-icon-nuxt: "\ea24";
$web-icon-platform: "\ea25";
$web-icon-play: "\ea26";
$web-icon-plus: "\ea27";
$web-icon-product-hunt: "\ea28";
$web-icon-refine: "\ea29";
$web-icon-rest: "\ea2a";
$web-icon-search: "\ea2b";
$web-icon-sendgrid: "\ea2c";
$web-icon-star: "\ea2d";
$web-icon-system: "\ea2e";
$web-icon-textmagic: "\ea2f";
$web-icon-twitter: "\ea30";
$web-icon-vue: "\ea31";
$web-icon-x: "\ea32";
$web-icon-youtube: "\ea33";

View File

@@ -95,208 +95,214 @@
"className": "web-icon-copy",
"unicode": "&#59920;"
},
"dark": {
"daily-dev": {
"encodedCode": "\\ea11",
"prefix": "web-icon",
"className": "web-icon-dark",
"className": "web-icon-daily-dev",
"unicode": "&#59921;"
},
"discord": {
"dark": {
"encodedCode": "\\ea12",
"prefix": "web-icon",
"className": "web-icon-discord",
"className": "web-icon-dark",
"unicode": "&#59922;"
},
"divider-vertical": {
"discord": {
"encodedCode": "\\ea13",
"prefix": "web-icon",
"className": "web-icon-divider-vertical",
"className": "web-icon-discord",
"unicode": "&#59923;"
},
"download": {
"divider-vertical": {
"encodedCode": "\\ea14",
"prefix": "web-icon",
"className": "web-icon-download",
"className": "web-icon-divider-vertical",
"unicode": "&#59924;"
},
"ext-link": {
"download": {
"encodedCode": "\\ea15",
"prefix": "web-icon",
"className": "web-icon-ext-link",
"className": "web-icon-download",
"unicode": "&#59925;"
},
"firebase": {
"ext-link": {
"encodedCode": "\\ea16",
"prefix": "web-icon",
"className": "web-icon-firebase",
"className": "web-icon-ext-link",
"unicode": "&#59926;"
},
"github": {
"firebase": {
"encodedCode": "\\ea17",
"prefix": "web-icon",
"className": "web-icon-github",
"className": "web-icon-firebase",
"unicode": "&#59927;"
},
"google": {
"github": {
"encodedCode": "\\ea18",
"prefix": "web-icon",
"className": "web-icon-google",
"className": "web-icon-github",
"unicode": "&#59928;"
},
"hamburger-menu": {
"google": {
"encodedCode": "\\ea19",
"prefix": "web-icon",
"className": "web-icon-hamburger-menu",
"className": "web-icon-google",
"unicode": "&#59929;"
},
"light": {
"hamburger-menu": {
"encodedCode": "\\ea1a",
"prefix": "web-icon",
"className": "web-icon-light",
"className": "web-icon-hamburger-menu",
"unicode": "&#59930;"
},
"linkedin": {
"light": {
"encodedCode": "\\ea1b",
"prefix": "web-icon",
"className": "web-icon-linkedin",
"className": "web-icon-light",
"unicode": "&#59931;"
},
"location": {
"linkedin": {
"encodedCode": "\\ea1c",
"prefix": "web-icon",
"className": "web-icon-location",
"className": "web-icon-linkedin",
"unicode": "&#59932;"
},
"logout-left": {
"location": {
"encodedCode": "\\ea1d",
"prefix": "web-icon",
"className": "web-icon-logout-left",
"className": "web-icon-location",
"unicode": "&#59933;"
},
"logout-right": {
"logout-left": {
"encodedCode": "\\ea1e",
"prefix": "web-icon",
"className": "web-icon-logout-right",
"className": "web-icon-logout-left",
"unicode": "&#59934;"
},
"mailgun": {
"logout-right": {
"encodedCode": "\\ea1f",
"prefix": "web-icon",
"className": "web-icon-mailgun",
"className": "web-icon-logout-right",
"unicode": "&#59935;"
},
"message": {
"mailgun": {
"encodedCode": "\\ea20",
"prefix": "web-icon",
"className": "web-icon-message",
"className": "web-icon-mailgun",
"unicode": "&#59936;"
},
"microsoft": {
"message": {
"encodedCode": "\\ea21",
"prefix": "web-icon",
"className": "web-icon-microsoft",
"className": "web-icon-message",
"unicode": "&#59937;"
},
"minus": {
"microsoft": {
"encodedCode": "\\ea22",
"prefix": "web-icon",
"className": "web-icon-minus",
"className": "web-icon-microsoft",
"unicode": "&#59938;"
},
"nuxt": {
"minus": {
"encodedCode": "\\ea23",
"prefix": "web-icon",
"className": "web-icon-nuxt",
"className": "web-icon-minus",
"unicode": "&#59939;"
},
"platform": {
"nuxt": {
"encodedCode": "\\ea24",
"prefix": "web-icon",
"className": "web-icon-platform",
"className": "web-icon-nuxt",
"unicode": "&#59940;"
},
"play": {
"platform": {
"encodedCode": "\\ea25",
"prefix": "web-icon",
"className": "web-icon-play",
"className": "web-icon-platform",
"unicode": "&#59941;"
},
"plus": {
"play": {
"encodedCode": "\\ea26",
"prefix": "web-icon",
"className": "web-icon-plus",
"className": "web-icon-play",
"unicode": "&#59942;"
},
"product-hunt": {
"plus": {
"encodedCode": "\\ea27",
"prefix": "web-icon",
"className": "web-icon-product-hunt",
"className": "web-icon-plus",
"unicode": "&#59943;"
},
"refine": {
"product-hunt": {
"encodedCode": "\\ea28",
"prefix": "web-icon",
"className": "web-icon-refine",
"className": "web-icon-product-hunt",
"unicode": "&#59944;"
},
"rest": {
"refine": {
"encodedCode": "\\ea29",
"prefix": "web-icon",
"className": "web-icon-rest",
"className": "web-icon-refine",
"unicode": "&#59945;"
},
"search": {
"rest": {
"encodedCode": "\\ea2a",
"prefix": "web-icon",
"className": "web-icon-search",
"className": "web-icon-rest",
"unicode": "&#59946;"
},
"sendgrid": {
"search": {
"encodedCode": "\\ea2b",
"prefix": "web-icon",
"className": "web-icon-sendgrid",
"className": "web-icon-search",
"unicode": "&#59947;"
},
"star": {
"sendgrid": {
"encodedCode": "\\ea2c",
"prefix": "web-icon",
"className": "web-icon-star",
"className": "web-icon-sendgrid",
"unicode": "&#59948;"
},
"system": {
"star": {
"encodedCode": "\\ea2d",
"prefix": "web-icon",
"className": "web-icon-system",
"className": "web-icon-star",
"unicode": "&#59949;"
},
"textmagic": {
"system": {
"encodedCode": "\\ea2e",
"prefix": "web-icon",
"className": "web-icon-textmagic",
"className": "web-icon-system",
"unicode": "&#59950;"
},
"twitter": {
"textmagic": {
"encodedCode": "\\ea2f",
"prefix": "web-icon",
"className": "web-icon-twitter",
"className": "web-icon-textmagic",
"unicode": "&#59951;"
},
"vue": {
"twitter": {
"encodedCode": "\\ea30",
"prefix": "web-icon",
"className": "web-icon-vue",
"className": "web-icon-twitter",
"unicode": "&#59952;"
},
"x": {
"vue": {
"encodedCode": "\\ea31",
"prefix": "web-icon",
"className": "web-icon-x",
"className": "web-icon-vue",
"unicode": "&#59953;"
},
"youtube": {
"x": {
"encodedCode": "\\ea32",
"prefix": "web-icon",
"className": "web-icon-youtube",
"className": "web-icon-x",
"unicode": "&#59954;"
},
"youtube": {
"encodedCode": "\\ea33",
"prefix": "web-icon",
"className": "web-icon-youtube",
"unicode": "&#59955;"
}
}

View File

@@ -20,153 +20,54 @@
-moz-osx-font-smoothing: grayscale;
}
.web-icon-apple:before {
content: '\ea01';
}
.web-icon-appwrite:before {
content: '\ea02';
}
.web-icon-arrow-down:before {
content: '\ea03';
}
.web-icon-arrow-ext-link:before {
content: '\ea04';
}
.web-icon-arrow-left:before {
content: '\ea05';
}
.web-icon-arrow-right:before {
content: '\ea06';
}
.web-icon-arrow-up:before {
content: '\ea07';
}
.web-icon-calendar:before {
content: '\ea08';
}
.web-icon-check:before {
content: '\ea09';
}
.web-icon-chevron-down:before {
content: '\ea0a';
}
.web-icon-chevron-left:before {
content: '\ea0b';
}
.web-icon-chevron-right:before {
content: '\ea0c';
}
.web-icon-chevron-up:before {
content: '\ea0d';
}
.web-icon-close:before {
content: '\ea0e';
}
.web-icon-command:before {
content: '\ea0f';
}
.web-icon-copy:before {
content: '\ea10';
}
.web-icon-dark:before {
content: '\ea11';
}
.web-icon-discord:before {
content: '\ea12';
}
.web-icon-divider-vertical:before {
content: '\ea13';
}
.web-icon-download:before {
content: '\ea14';
}
.web-icon-ext-link:before {
content: '\ea15';
}
.web-icon-firebase:before {
content: '\ea16';
}
.web-icon-github:before {
content: '\ea17';
}
.web-icon-google:before {
content: '\ea18';
}
.web-icon-hamburger-menu:before {
content: '\ea19';
}
.web-icon-light:before {
content: '\ea1a';
}
.web-icon-linkedin:before {
content: '\ea1b';
}
.web-icon-location:before {
content: '\ea1c';
}
.web-icon-logout-left:before {
content: '\ea1d';
}
.web-icon-logout-right:before {
content: '\ea1e';
}
.web-icon-mailgun:before {
content: '\ea1f';
}
.web-icon-message:before {
content: '\ea20';
}
.web-icon-microsoft:before {
content: '\ea21';
}
.web-icon-minus:before {
content: '\ea22';
}
.web-icon-nuxt:before {
content: '\ea23';
}
.web-icon-platform:before {
content: '\ea24';
}
.web-icon-play:before {
content: '\ea25';
}
.web-icon-plus:before {
content: '\ea26';
}
.web-icon-product-hunt:before {
content: '\ea27';
}
.web-icon-refine:before {
content: '\ea28';
}
.web-icon-rest:before {
content: '\ea29';
}
.web-icon-search:before {
content: '\ea2a';
}
.web-icon-sendgrid:before {
content: '\ea2b';
}
.web-icon-star:before {
content: '\ea2c';
}
.web-icon-system:before {
content: '\ea2d';
}
.web-icon-textmagic:before {
content: '\ea2e';
}
.web-icon-twitter:before {
content: '\ea2f';
}
.web-icon-vue:before {
content: '\ea30';
}
.web-icon-x:before {
content: '\ea31';
}
.web-icon-youtube:before {
content: '\ea32';
}
.web-icon-apple:before { content: "\ea01"; }
.web-icon-appwrite:before { content: "\ea02"; }
.web-icon-arrow-down:before { content: "\ea03"; }
.web-icon-arrow-ext-link:before { content: "\ea04"; }
.web-icon-arrow-left:before { content: "\ea05"; }
.web-icon-arrow-right:before { content: "\ea06"; }
.web-icon-arrow-up:before { content: "\ea07"; }
.web-icon-calendar:before { content: "\ea08"; }
.web-icon-check:before { content: "\ea09"; }
.web-icon-chevron-down:before { content: "\ea0a"; }
.web-icon-chevron-left:before { content: "\ea0b"; }
.web-icon-chevron-right:before { content: "\ea0c"; }
.web-icon-chevron-up:before { content: "\ea0d"; }
.web-icon-close:before { content: "\ea0e"; }
.web-icon-command:before { content: "\ea0f"; }
.web-icon-copy:before { content: "\ea10"; }
.web-icon-daily-dev:before { content: "\ea11"; }
.web-icon-dark:before { content: "\ea12"; }
.web-icon-discord:before { content: "\ea13"; }
.web-icon-divider-vertical:before { content: "\ea14"; }
.web-icon-download:before { content: "\ea15"; }
.web-icon-ext-link:before { content: "\ea16"; }
.web-icon-firebase:before { content: "\ea17"; }
.web-icon-github:before { content: "\ea18"; }
.web-icon-google:before { content: "\ea19"; }
.web-icon-hamburger-menu:before { content: "\ea1a"; }
.web-icon-light:before { content: "\ea1b"; }
.web-icon-linkedin:before { content: "\ea1c"; }
.web-icon-location:before { content: "\ea1d"; }
.web-icon-logout-left:before { content: "\ea1e"; }
.web-icon-logout-right:before { content: "\ea1f"; }
.web-icon-mailgun:before { content: "\ea20"; }
.web-icon-message:before { content: "\ea21"; }
.web-icon-microsoft:before { content: "\ea22"; }
.web-icon-minus:before { content: "\ea23"; }
.web-icon-nuxt:before { content: "\ea24"; }
.web-icon-platform:before { content: "\ea25"; }
.web-icon-play:before { content: "\ea26"; }
.web-icon-plus:before { content: "\ea27"; }
.web-icon-product-hunt:before { content: "\ea28"; }
.web-icon-refine:before { content: "\ea29"; }
.web-icon-rest:before { content: "\ea2a"; }
.web-icon-search:before { content: "\ea2b"; }
.web-icon-sendgrid:before { content: "\ea2c"; }
.web-icon-star:before { content: "\ea2d"; }
.web-icon-system:before { content: "\ea2e"; }
.web-icon-textmagic:before { content: "\ea2f"; }
.web-icon-twitter:before { content: "\ea30"; }
.web-icon-vue:before { content: "\ea31"; }
.web-icon-x:before { content: "\ea32"; }
.web-icon-youtube:before { content: "\ea33"; }

Binary file not shown.

View File

@@ -32,40 +32,41 @@
.web-icon-close:before { content: "\ea0e"; }
.web-icon-command:before { content: "\ea0f"; }
.web-icon-copy:before { content: "\ea10"; }
.web-icon-dark:before { content: "\ea11"; }
.web-icon-discord:before { content: "\ea12"; }
.web-icon-divider-vertical:before { content: "\ea13"; }
.web-icon-download:before { content: "\ea14"; }
.web-icon-ext-link:before { content: "\ea15"; }
.web-icon-firebase:before { content: "\ea16"; }
.web-icon-github:before { content: "\ea17"; }
.web-icon-google:before { content: "\ea18"; }
.web-icon-hamburger-menu:before { content: "\ea19"; }
.web-icon-light:before { content: "\ea1a"; }
.web-icon-linkedin:before { content: "\ea1b"; }
.web-icon-location:before { content: "\ea1c"; }
.web-icon-logout-left:before { content: "\ea1d"; }
.web-icon-logout-right:before { content: "\ea1e"; }
.web-icon-mailgun:before { content: "\ea1f"; }
.web-icon-message:before { content: "\ea20"; }
.web-icon-microsoft:before { content: "\ea21"; }
.web-icon-minus:before { content: "\ea22"; }
.web-icon-nuxt:before { content: "\ea23"; }
.web-icon-platform:before { content: "\ea24"; }
.web-icon-play:before { content: "\ea25"; }
.web-icon-plus:before { content: "\ea26"; }
.web-icon-product-hunt:before { content: "\ea27"; }
.web-icon-refine:before { content: "\ea28"; }
.web-icon-rest:before { content: "\ea29"; }
.web-icon-search:before { content: "\ea2a"; }
.web-icon-sendgrid:before { content: "\ea2b"; }
.web-icon-star:before { content: "\ea2c"; }
.web-icon-system:before { content: "\ea2d"; }
.web-icon-textmagic:before { content: "\ea2e"; }
.web-icon-twitter:before { content: "\ea2f"; }
.web-icon-vue:before { content: "\ea30"; }
.web-icon-x:before { content: "\ea31"; }
.web-icon-youtube:before { content: "\ea32"; }
.web-icon-daily-dev:before { content: "\ea11"; }
.web-icon-dark:before { content: "\ea12"; }
.web-icon-discord:before { content: "\ea13"; }
.web-icon-divider-vertical:before { content: "\ea14"; }
.web-icon-download:before { content: "\ea15"; }
.web-icon-ext-link:before { content: "\ea16"; }
.web-icon-firebase:before { content: "\ea17"; }
.web-icon-github:before { content: "\ea18"; }
.web-icon-google:before { content: "\ea19"; }
.web-icon-hamburger-menu:before { content: "\ea1a"; }
.web-icon-light:before { content: "\ea1b"; }
.web-icon-linkedin:before { content: "\ea1c"; }
.web-icon-location:before { content: "\ea1d"; }
.web-icon-logout-left:before { content: "\ea1e"; }
.web-icon-logout-right:before { content: "\ea1f"; }
.web-icon-mailgun:before { content: "\ea20"; }
.web-icon-message:before { content: "\ea21"; }
.web-icon-microsoft:before { content: "\ea22"; }
.web-icon-minus:before { content: "\ea23"; }
.web-icon-nuxt:before { content: "\ea24"; }
.web-icon-platform:before { content: "\ea25"; }
.web-icon-play:before { content: "\ea26"; }
.web-icon-plus:before { content: "\ea27"; }
.web-icon-product-hunt:before { content: "\ea28"; }
.web-icon-refine:before { content: "\ea29"; }
.web-icon-rest:before { content: "\ea2a"; }
.web-icon-search:before { content: "\ea2b"; }
.web-icon-sendgrid:before { content: "\ea2c"; }
.web-icon-star:before { content: "\ea2d"; }
.web-icon-system:before { content: "\ea2e"; }
.web-icon-textmagic:before { content: "\ea2f"; }
.web-icon-twitter:before { content: "\ea30"; }
.web-icon-vue:before { content: "\ea31"; }
.web-icon-x:before { content: "\ea32"; }
.web-icon-youtube:before { content: "\ea33"; }
$web-icon-apple: "\ea01";
$web-icon-appwrite: "\ea02";
@@ -83,37 +84,38 @@ $web-icon-chevron-up: "\ea0d";
$web-icon-close: "\ea0e";
$web-icon-command: "\ea0f";
$web-icon-copy: "\ea10";
$web-icon-dark: "\ea11";
$web-icon-discord: "\ea12";
$web-icon-divider-vertical: "\ea13";
$web-icon-download: "\ea14";
$web-icon-ext-link: "\ea15";
$web-icon-firebase: "\ea16";
$web-icon-github: "\ea17";
$web-icon-google: "\ea18";
$web-icon-hamburger-menu: "\ea19";
$web-icon-light: "\ea1a";
$web-icon-linkedin: "\ea1b";
$web-icon-location: "\ea1c";
$web-icon-logout-left: "\ea1d";
$web-icon-logout-right: "\ea1e";
$web-icon-mailgun: "\ea1f";
$web-icon-message: "\ea20";
$web-icon-microsoft: "\ea21";
$web-icon-minus: "\ea22";
$web-icon-nuxt: "\ea23";
$web-icon-platform: "\ea24";
$web-icon-play: "\ea25";
$web-icon-plus: "\ea26";
$web-icon-product-hunt: "\ea27";
$web-icon-refine: "\ea28";
$web-icon-rest: "\ea29";
$web-icon-search: "\ea2a";
$web-icon-sendgrid: "\ea2b";
$web-icon-star: "\ea2c";
$web-icon-system: "\ea2d";
$web-icon-textmagic: "\ea2e";
$web-icon-twitter: "\ea2f";
$web-icon-vue: "\ea30";
$web-icon-x: "\ea31";
$web-icon-youtube: "\ea32";
$web-icon-daily-dev: "\ea11";
$web-icon-dark: "\ea12";
$web-icon-discord: "\ea13";
$web-icon-divider-vertical: "\ea14";
$web-icon-download: "\ea15";
$web-icon-ext-link: "\ea16";
$web-icon-firebase: "\ea17";
$web-icon-github: "\ea18";
$web-icon-google: "\ea19";
$web-icon-hamburger-menu: "\ea1a";
$web-icon-light: "\ea1b";
$web-icon-linkedin: "\ea1c";
$web-icon-location: "\ea1d";
$web-icon-logout-left: "\ea1e";
$web-icon-logout-right: "\ea1f";
$web-icon-mailgun: "\ea20";
$web-icon-message: "\ea21";
$web-icon-microsoft: "\ea22";
$web-icon-minus: "\ea23";
$web-icon-nuxt: "\ea24";
$web-icon-platform: "\ea25";
$web-icon-play: "\ea26";
$web-icon-plus: "\ea27";
$web-icon-product-hunt: "\ea28";
$web-icon-refine: "\ea29";
$web-icon-rest: "\ea2a";
$web-icon-search: "\ea2b";
$web-icon-sendgrid: "\ea2c";
$web-icon-star: "\ea2d";
$web-icon-system: "\ea2e";
$web-icon-textmagic: "\ea2f";
$web-icon-twitter: "\ea30";
$web-icon-vue: "\ea31";
$web-icon-x: "\ea32";
$web-icon-youtube: "\ea33";

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 165 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Logo/Dark" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icon" transform="translate(4.000000, 11.000000)" fill="#151618">
<g id="Secound" opacity="0.56" transform="translate(21.000000, 0.930000)">
<path d="M6.47910463,8.01371418 L2.94663391,4.48124347 L4.71194884,0.95 L10.4515234,6.68957458 C11.1828255,7.42087669 11.1828255,8.60655167 10.4515234,9.33785378 L3.38719562,16.4021816 C2.65589351,17.1334837 1.47021853,17.1334837 0.738916421,16.4021816 C0.00761431424,15.6708795 0.00761431424,14.4852045 0.738916421,13.7539024 L6.47910463,8.01371418 Z" id="Combined-Shape"></path>
</g>
<path d="M21.7402327,0.548323198 C22.4715349,-0.182978908 23.6575166,-0.182672097 24.3888188,0.54863001 L25.7132652,1.87307642 L10.2610836,17.325258 C9.52978147,18.0565601 8.34379968,18.0562533 7.61249757,17.3249512 L6.28805116,16.0005048 L21.7402327,0.548323198 Z M15.1176939,5.40493351 L12.4688011,8.05382633 L8.93633036,4.52135561 L4.52089537,8.9367906 L8.05336609,12.4692613 L6.28805116,16.0005048 L0.54847658,10.2609302 C-0.182825527,9.52962809 -0.182825527,8.34395311 0.54847658,7.612651 L7.61249757,0.54863001 C8.34379968,-0.182672097 9.52978147,-0.182978908 10.2610836,0.548323198 L15.1176939,5.40493351 Z" id="Main"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,12 @@
export const autoHash = (
node: Element,
callback: (entries: IntersectionObserverEntry[]) => void
) => {
const observer = new IntersectionObserver(callback, {
threshold: 1
});
observer.observe(node);
return { destroy: () => observer.disconnect() };
};

View File

@@ -41,6 +41,7 @@
],
Learn: [
{ label: 'Docs', href: '/docs' },
{ label: 'Integrations', href: '/integrations' },
{ label: 'Community', href: '/community' },
{ label: 'Init', href: '/init' },
{ label: 'Threads', href: '/threads' },

View File

@@ -0,0 +1,145 @@
<div class="web-big-padding-section-level-2">
<div class="web-container">
<h3 class="web-label web-u-color-text-primary u-text-center">
Keep exploring similar integrations
</h3>
<ul class="u-margin-block-start-32 l-grid-1">
<li>
<a
href="/docs/products/auth"
class="web-card product-card is-transparent u-block u-height-100-percent"
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem;"
>
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/auth.png"
alt=""
class=""
width="32"
height="32"
/>
<h4 class="web-main-body-400 web-u-color-text-primary">Auth</h4>
<span class="icon-arrow-right u-margin-inline-start-auto" aria-hidden="true"
></span>
</div>
<p class="web-sub-body-400 u-margin-block-start-4">
Build secure authentication and manage your users.
</p>
</a>
</li>
<li>
<a
href="/docs/products/functions"
class="web-card product-card is-transparent u-block u-height-100-percent"
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem;"
>
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/functions.png"
alt=""
class=""
width="32"
height="32"
/>
<h4 class="web-main-body-400 web-u-color-text-primary">Functions</h4>
<span class="icon-arrow-right u-margin-inline-start-auto" aria-hidden="true"
></span>
</div>
<p class="web-sub-body-400 u-margin-block-start-4">
Scale big and unlock limitless potential with Appwrite functions.
</p>
</a>
</li>
<li>
<a
href="/docs/products/databases"
class="web-card product-card is-transparent u-block u-height-100-percent"
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem;"
>
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/databases.png"
alt=""
class=""
width="32"
height="32"
/>
<h4 class="web-main-body-400 web-u-color-text-primary">Databases</h4>
<span class="icon-arrow-right u-margin-inline-start-auto" aria-hidden="true"
></span>
</div>
<p class="web-sub-body-400 u-margin-block-start-4">
Store and query structured data, ensuring scalable storage.
</p>
</a>
</li>
<li>
<a
href="/docs/products/messaging"
class="web-card product-card is-transparent u-block u-height-100-percent"
style="--card-padding:1.5rem;--card-padding-mobile:1.5rem;"
>
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/messaging.png"
alt=""
class=""
width="32"
height="32"
/>
<h4 class="web-main-body-400 web-u-color-text-primary">Messaging</h4>
<span class="icon-arrow-right u-margin-inline-start-auto" aria-hidden="true"
></span>
</div>
<p class="web-sub-body-400 u-margin-block-start-4">
Manage your files project, using convenient APIs and utilities.
</p>
</a>
</li>
<li>
<a
href="/docs/apis/realtime"
class="web-card product-card is-transparent u-block u-height-100-percent"
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem;"
>
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/realtime.png"
alt=""
class=""
width="32"
height="32"
/>
<h4 class="web-main-body-400 web-u-color-text-primary">Realtime</h4>
<span class="icon-arrow-right u-margin-inline-start-auto" aria-hidden="true"
></span>
</div>
<p class="web-sub-body-400 u-margin-block-start-4">
Utilize realtime information from all Appwrite services.
</p>
</a>
</li>
</ul>
</div>
</div>
<style lang="scss">
.l-grid-1 {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 2rem;
@media (max-width: 600px) {
gap: 1.25rem;
}
.product-card {
transition: all 100ms ease-in-out;
box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0);
&:hover {
box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0.12);
}
}
}
</style>

View File

@@ -0,0 +1,168 @@
<script lang="ts">
import embla from 'embla-carousel-svelte';
import {
type EmblaCarouselType,
type EmblaEventType,
type EmblaOptionsType,
type EmblaPluginType
} from 'embla-carousel';
import { WheelGesturesPlugin } from 'embla-carousel-wheel-gestures';
let emblaApi: EmblaCarouselType;
let options: EmblaOptionsType = {
align: 'center',
skipSnaps: true,
loop: true
};
let hasPrev: boolean = false;
let hasNext: boolean = true;
const togglePrevNextBtnsState = () => {
if (emblaApi.canScrollPrev()) hasPrev = true;
else hasPrev = false;
if (emblaApi.canScrollNext()) hasNext = true;
else hasNext = false;
};
let plugins: EmblaPluginType[] = [WheelGesturesPlugin()];
let selectedScrollIndex = 0;
const onSelect = (index: number) => {
emblaApi.scrollTo(index);
selectedScrollIndex = emblaApi.selectedScrollSnap();
};
const onPrev = () => {
emblaApi.scrollPrev();
selectedScrollIndex = emblaApi.selectedScrollSnap();
};
const onNext = () => {
emblaApi.scrollNext();
selectedScrollIndex = emblaApi.selectedScrollSnap();
};
const TWEEN_FACTOR_BASE = 0.52;
let tweenFactor = 0;
let tweenNodes: HTMLElement[] = [];
const numberWithinRange = (number: number, min: number, max: number) =>
Math.min(Math.max(number, min), max);
const setTweenNodes = (emblaApi: EmblaCarouselType): void => {
tweenNodes = emblaApi.slideNodes().map((slideNode) => {
return slideNode.querySelector('.embla__slide__number') as HTMLElement;
});
};
const setTweenFactor = (emblaApi: EmblaCarouselType): void => {
tweenFactor = TWEEN_FACTOR_BASE * emblaApi.scrollSnapList().length;
};
const tweenScale = (emblaApi: EmblaCarouselType, eventName?: EmblaEventType): void => {
const engine = emblaApi.internalEngine();
const scrollProgress = emblaApi.scrollProgress();
const slidesInView = emblaApi.slidesInView();
const isScrollEvent = eventName === 'scroll';
emblaApi.scrollSnapList().forEach((scrollSnap, snapIndex) => {
let diffToTarget = scrollSnap - scrollProgress;
const slidesInSnap = engine.slideRegistry[snapIndex];
slidesInSnap.forEach((slideIndex) => {
if (isScrollEvent && !slidesInView.includes(slideIndex)) return;
if (engine.options.loop) {
engine.slideLooper.loopPoints.forEach((loopItem) => {
const target = loopItem.target();
if (slideIndex === loopItem.index && target !== 0) {
const sign = Math.sign(target);
if (sign === -1) {
diffToTarget = scrollSnap - (1 + scrollProgress);
}
if (sign === 1) {
diffToTarget = scrollSnap + (1 - scrollProgress);
}
}
});
}
const tweenValue = 1 - Math.abs(diffToTarget * tweenFactor);
const scale = numberWithinRange(tweenValue, 0.8, 1).toString();
const tweenNode = tweenNodes[slideIndex];
tweenNode.style.transform = `scale(${scale})`;
});
});
};
const onEmblaInit = (event: CustomEvent<EmblaCarouselType>) => {
emblaApi = event.detail;
setTweenNodes(emblaApi);
setTweenFactor(emblaApi);
tweenScale(emblaApi);
emblaApi
.on('scroll', () => {
selectedScrollIndex = emblaApi.selectedScrollSnap();
})
.on('init', togglePrevNextBtnsState)
.on('select', togglePrevNextBtnsState)
.on('reInit', togglePrevNextBtnsState)
.on('reInit', setTweenNodes)
.on('reInit', setTweenFactor)
.on('reInit', tweenScale)
.on('scroll', tweenScale)
.on('slideFocus', tweenScale);
};
</script>
<div class="embla web-carousel">
{#if hasPrev}
<button class="web-carousel-button web-carousel-button-start" on:click={onPrev}>
<span class="web-icon-arrow-left" aria-hidden="true"></span>
</button>
{/if}
{#if hasNext}
<button class="web-carousel-button web-carousel-button-end" on:click={onNext}>
<span class="web-icon-arrow-right" aria-hidden="true"></span>
</button>
{/if}
<div class="embla__viewport" use:embla={{ options, plugins }} on:emblaInit={onEmblaInit}>
<ul class="embla__container">
<slot />
</ul>
</div>
</div>
<div class="web-carousel-bullets">
<ul class="web-carousel-bullets-list">
{#each Array.from({ length: emblaApi?.scrollSnapList().length }) as _, i}
<li class="web-carousel-bullets-item">
<button
class="web-carousel-bullets-button"
class:is-selected={selectedScrollIndex === i}
aria-label={`gallery item ${i + 1}`}
on:click={() => onSelect(i)}
></button>
</li>
{/each}
</ul>
</div>
<style>
.embla {
overflow: hidden;
position: relative;
}
.embla__container {
display: flex;
}
</style>

View File

@@ -0,0 +1,25 @@
<li class="slide web-carousel-item">
<div class="embla__slide__number">
<slot />
</div>
</li>
<style lang="scss">
@use '$scss/abstract' as *;
.slide {
cursor: grab;
&:active {
cursor: grabbing;
}
@media (max-width: 768px) {
flex: 0 0 100%;
}
flex: 0 0 50%;
min-width: 0;
margin-right: pxToRem(16);
}
</style>

View File

@@ -0,0 +1,2 @@
export { default as Root } from './Carousel.svelte';
export { default as Slide } from './CarouselSlide.svelte';

View File

@@ -1,4 +1,4 @@
export const GITHUB_STARS = '41.9K';
export const GITHUB_STARS = '42.8K';
export const BANNER_KEY = 'discord-banner-01'; // Change key to force banner to show again
export const SENTRY_DSN =
'https://27d41dc8bb67b596f137924ab8599e59@o1063647.ingest.us.sentry.io/4507497727000576';
@@ -40,5 +40,10 @@ export const socials: Array<Social> = [
icon: 'web-icon-youtube',
label: 'YouTube',
link: 'https://www.youtube.com/c/appwrite?sub_confirmation=1'
},
{
icon: 'web-icon-daily-dev',
label: 'Daily.dev',
link: 'https://app.daily.dev/squads/appwrite'
}
];

View File

@@ -0,0 +1,17 @@
<script lang="ts" generics="T">
import Fuse, { type IFuseOptions, type FuseResult } from 'fuse.js';
export let list: ReadonlyArray<T>;
export let options: IFuseOptions<T>;
export let query: string;
export let result: FuseResult<T>[];
$: fuse = new Fuse(list, options);
$: if (list) {
fuse.setCollection(list);
}
$: if (list || query) {
result = fuse.search(query);
}
</script>

View File

@@ -0,0 +1,6 @@
import type { FuseResult } from 'fuse.js';
// Reexport your entry components here
export { default as Fuse } from './Fuse.svelte';
export type ResultType<T> = FuseResult<T>[];

View File

@@ -1,5 +1,5 @@
<script lang="ts" context="module">
import { writable } from "svelte/store";
import { writable } from 'svelte/store';
export type NavLink = {
label: string;
@@ -36,8 +36,95 @@
observer.observe(document.body, { childList: true, subtree: true });
const callbacks = [
addEventListener(window, "scroll", handleVisibility),
addEventListener(window, "resize", handleVisibility),
addEventListener(window, 'scroll', handleVisibility),
addEventListener(window, 'resize', handleVisibility)
];
return () => {
observer.disconnect();
callbacks.forEach((callback) => callback());
};
}
function isInViewport(element: Element): boolean {
const mobileHeader = document.querySelector('.aw-mobile-header');
const isMobile =
mobileHeader &&
getComputedStyle(mobileHeader).display !== 'none' &&
isVisible(mobileHeader, {
top: 0,
bottom: window.innerHeight,
left: 0,
right: window.innerWidth
});
const h = isMobile || 'bannerHidden' in document.body.dataset ? 32 : 64;
return isVisible(element, {
top: h,
bottom: h,
left: 0,
right: window.innerWidth
});
}
function getVisibleTheme() {
const themes = Array.from(document.querySelectorAll('.theme-dark, .theme-light')).filter(
(element) => {
const { classList, dataset } = element as HTMLElement;
if (
classList.contains('web-mobile-header') ||
classList.contains('web-main-header') ||
element === document.body ||
typeof dataset['themeIgnore'] === 'string'
) {
return false;
}
return true;
}
);
for (const theme of themes) {
if (isInViewport(theme)) {
return theme.classList.contains('theme-light') ? 'light' : 'dark';
}
}
return 'dark';
}
onMount(() => {
setTimeout(() => {
$initialized = true;
}, 1000);
return setupThemeObserver();
});
let navLinks: NavLink[] = [
{
label: 'Docs',
href: '/docs'
},
{
label: 'Community',
href: '/community'
},
{
label: 'Blog',
href: '/blog'
},
{
label: 'Integrations',
href: '/integrations'
},
{
label: 'Changelog',
href: '/changelog',
showBadge: hasNewChangelog?.() && !$page.url.pathname.includes('/changelog')
},
{
label: 'Pricing',
href: '/pricing'
}
];
return () => {
@@ -236,8 +323,8 @@
<a
class="web-link"
href={navLink.href}
data-initialized={$initialized ? "" : undefined}
data-badge={navLink.showBadge ? "" : undefined}
data-initialized={$initialized ? '' : undefined}
data-badge={navLink.showBadge ? '' : undefined}
>{navLink.label}
</a>
</li>
@@ -265,7 +352,7 @@
<main
class="web-main-section"
class:web-u-hide-mobile={$isMobileNavOpen}
id={omitMainId ? undefined : "main"}
id={omitMainId ? undefined : 'main'}
>
<slot />
</main>
@@ -290,7 +377,7 @@
position: relative;
&::after {
content: "";
content: '';
position: absolute;
background-color: hsl(var(--web-color-accent));
border-radius: 100%;

View File

@@ -1,8 +1,8 @@
import type { AuthorData, PostsData } from '$routes/blog/content';
export const DEFAULT_HOST = 'https://appwrite.io';
export const DEFAULT_DESCRIPTION =
'Appwrite is an open-source platform for building applications at any scale, using your preferred programming languages and tools.';
export const DEFAULT_DESCRIPTION = 'Appwrite is an open-source backend platform offering essential APIs for building web and mobile applications.';
export function buildOpenGraphImage(title: string, description: string): string {
return `https://og.appwrite.global/image.png?title=${encodeURIComponent(
title

View File

@@ -0,0 +1,244 @@
<script lang="ts">
import { Root, Slide } from '$lib/components/carousel';
import FooterNav from '$lib/components/FooterNav.svelte';
import MainFooter from '$lib/components/MainFooter.svelte';
import ProductsGrid from '$lib/components/ProductsGrid.svelte';
import { Main } from '$lib/layouts';
import { DEFAULT_HOST } from '$lib/utils/metadata';
import type { Integration } from '$routes/integrations/+page';
import { isHeaderHidden } from '$lib/layouts/Main.svelte';
export let title: Integration['title'];
export let images: Integration['images'];
// export let isNew: Integration['isNew'];
export let isPartner: Integration['isPartner'];
export let product: Integration['product'];
export let category: Integration['category'];
export let description: Integration['description'];
export let cover: Integration['cover'];
//const title = 'Integrations' + TITLE_SUFFIX;
//const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
const ogImage = DEFAULT_HOST + cover;
</script>
<svelte:head>
<!-- Titles -->
<title>{title}</title>
<meta property="og: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} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
</svelte:head>
<Main>
<div
class="web-u-sep-block-end u-padding-block-end-0"
style="background-color:rgba(23, 23, 26, 1); margin-block-end: 2.5rem"
>
<div class="web-container">
<div class="web-integrations-top-section">
<div class="web-carousel-wrapper">
<a href="/integrations" class="web-button is-text u-margin-block-end-48">
<span class="icon-cheveron-left" aria-hidden="true"></span>
<span>Back to catalog</span>
</a>
{#if images.length > 1}
<Root>
{#each images as slide}
<Slide>
<img
src={slide}
class="web-u-media-ratio-16-9"
alt="cover"
width="472"
/>
</Slide>
{/each}
</Root>
{:else}
<div
class="web-carousel-item"
style:max-width="584px"
style:margin="0 auto"
>
<img
src={images[0]}
class="web-u-media-ratio-16-9"
alt="cover"
width="472"
/>
</div>
{/if}
</div>
</div>
</div>
</div>
<div class="web-big-padding-section-level-1">
<div class="web-container">
<article class="u-flex-vertical web-u-gap-60-not-mobile web-u-gap-40-mobile">
<div class="l-grid-2-1 web-u-row-gap-56 web-u-gap-40-mobile">
<div class="l-grid-content">
<div class="u-flex u-cross-start u-gap-20">
<img
class="web-author-image"
src={product.avatar}
alt="Christy Jacob"
loading="lazy"
width="40"
height="40"
/>
<h1
class="web-title web-u-color-text-primary"
style="max-width: 28.15rem;"
>
{title}
</h1>
</div>
<div class="web-article">
<div class="web-article-content">
<slot />
</div>
</div>
</div>
<div class="l-grid-sidebar">
<dl
class="u-flex-vertical u-gap-20 sidebar-desc"
style:top={$isHeaderHidden ? '4rem' : '9rem'}
>
<div class="u-flex u-main-space-between u-gap-8">
<dt>Vendor</dt>
<dd class="web-u-color-text-primary">{product.vendor}</dd>
</div>
<div class="web-u-sep-block-end"></div>
{#if isPartner}
<div class="u-flex u-main-space-between u-gap-8">
<dt>Partner</dt>
<dd><div class="web-inline-tag">Verified</div></dd>
</div>
{/if}
<div class="web-u-sep-block-end"></div>
<div class="u-flex u-main-space-between u-gap-8">
<dt>Category</dt>
<dd class="web-u-color-text-primary">{category}</dd>
</div>
</dl>
</div>
</div>
</article>
</div>
</div>
<div
class="web-big-padding-section-level-1 u-overflow-hidden web-u-sep-block-start u-margin-block-start-48"
>
<!-- <ProductsGrid /> -->
<div class="web-container">
<div class="web-big-padding-section-level-2 u-position-relative">
<img
src="/images/bgs/pre-footer.png"
alt=""
class="web-pre-footer-bg"
style="z-index:-1"
/>
<!-- <div class="u-position-relative cta"> -->
<div class="u-position-relative">
<section
class="web-hero u-flex u-row-gap-16 u-main-center u-cross-center web-u-max-width-580"
>
<h2
class="web-display u-max-width-600 web-u-text-align-center web-u-color-text-primary"
>
Become a Technology Partner
</h2>
<p class="web-main-body-500">
Join our Technology Partners program to integrate your solutions with
Appwrites API, enhancing functionality and expanding your reach.
</p>
<a
href="/integrations/technology-partner"
class="web-button is-primary web-u-cross-child-center u-margin-block-start-16"
>
<span class="text">Get Started</span>
</a>
</section>
</div>
</div>
<FooterNav />
<MainFooter />
</div>
</div>
</Main>
<style lang="scss">
@use '$scss/abstract' as *;
.cta {
min-height: pxToRem(560);
display: flex;
align-items: center;
}
.web-pre-footer-bg {
position: absolute;
top: clamp(300px, 50vw, 50%);
left: clamp(300px, 50vw, 50%);
transform: translate(-58%, -52%);
width: clamp(1200px, 200vw, 3000px);
height: auto;
max-inline-size: unset;
max-block-size: unset;
}
/* more tha 9 items */
.l-side-column {
display: flex;
gap: pxToRem(16);
@media #{$break1} {
flex-direction: column;
}
}
.l-grid-2-1 {
@media #{$break1} {
display: flex;
flex-direction: column;
}
@media #{$break2open} {
display: grid;
gap: pxToRem(64);
grid-template-columns: repeat(12, 1fr);
}
.l-grid-content {
display: flex;
flex-direction: column;
gap: 32px;
grid-column: span 7 / span 7;
}
.l-grid-sidebar {
display: flex;
flex-direction: column;
gap: 32px;
grid-column: span 5 / span 5;
position: relative;
.sidebar-desc {
position: sticky;
left: 0;
}
}
}
</style>

View File

@@ -22,7 +22,7 @@
import { Main } from '$lib/layouts';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { DEFAULT_HOST } from '$lib/utils/metadata';
import { TITLE_SUFFIX } from '$routes/titles';
@@ -32,11 +32,12 @@
import { getContext, hasContext, setContext } from 'svelte';
export let title: string;
export let description: string;
export let transparentTableCells = false;
const seo = {
let seo = {
title: title + TITLE_SUFFIX,
description: DEFAULT_DESCRIPTION,
description: description,
ogImage: DEFAULT_HOST + '/images/open-graph/website.png',
APP_NAME: 'Appwrite'

View File

@@ -1,19 +1,19 @@
<script lang="ts">
import OpenSource from "$lib/animations/OpenSource.svelte";
import Products from "$lib/animations/Products/Products.svelte";
import ProductsMobile from "$lib/animations/Products/ProductsMobile.svelte";
import Button from "$lib/components/Button.svelte";
import LogoList from "$lib/components/LogoList.svelte";
import PreFooter from "$lib/components/PreFooter.svelte";
import Technologies from "$lib/components/Technologies.svelte";
import { Main } from "$lib/layouts";
import { isMobileNavOpen } from "$lib/layouts/Main.svelte";
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from "$lib/utils/metadata";
import FooterNav from "../lib/components/FooterNav.svelte";
import MainFooter from "../lib/components/MainFooter.svelte";
import DeveloperCard from "./DeveloperCard.svelte";
import OpenSource from '$lib/animations/OpenSource.svelte';
import Products from '$lib/animations/Products/Products.svelte';
import ProductsMobile from '$lib/animations/Products/ProductsMobile.svelte';
import Button from '$lib/components/Button.svelte';
import LogoList from '$lib/components/LogoList.svelte';
import PreFooter from '$lib/components/PreFooter.svelte';
import Technologies from '$lib/components/Technologies.svelte';
import { Main } from '$lib/layouts';
import { isMobileNavOpen } from '$lib/layouts/Main.svelte';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import FooterNav from '../lib/components/FooterNav.svelte';
import MainFooter from '../lib/components/MainFooter.svelte';
import DeveloperCard from './DeveloperCard.svelte';
const title = "Appwrite - Build like a team of hundreds";
const title = 'Appwrite - Build like a team of hundreds';
const description = DEFAULT_DESCRIPTION;
const ogImage = `${DEFAULT_HOST}/images/open-graph/website.png`;
</script>
@@ -69,28 +69,27 @@
</div>
<Main>
<Button on:click={() => alert("hello")}>Hello</Button>
<div class="web-big-padding-section hidden">
<div class="web-big-padding-section">
<div class="web-big-padding-section-level-1">
<div class="web-big-padding-section-level-2">
<section class="web-container web-u-padding-block-end-0">
<a
href="/blog/post/announcing-appwrite-new-ai-integrations"
href="/blog/post/announcing-appwrite-integration-catalog"
class="web-hero-banner-button web-u-margin-block-end-24"
>
<span class="web-icon-star" aria-hidden="true" />
<span class="web-caption-500">New</span>
<div class="web-hero-banner-button-sep" />
<span class="web-caption-400 web-u-trim-1"
>Announcing new AI Appwrite Integrations</span
>Announcing Appwrite's Integrations Catalog</span
>
<span class="web-icon-arrow-right" aria-hidden="true" />
</a>
<div class="web-hero is-horizontal">
<h1 class="web-headline">
<span class="web-gradient-text">
Build like a team of hundreds<span
class="web-u-color-text-accent">_</span
Build like a team of hundreds<span class="web-u-color-text-accent"
>_</span
>
</span>
</h1>
@@ -98,8 +97,8 @@
<p class="web-description">
Build your entire backend within minutes and scale effortlessly
using Appwrite's open-source platform. Add Authentication,
Databases, Functions, Storage, and Messaging to your projects
using the frameworks and languages of your choice.
Databases, Functions, Storage, and Messaging to your projects using
the frameworks and languages of your choice.
</p>
<a
href="https://cloud.appwrite.io"
@@ -111,6 +110,27 @@
</div>
</section>
</div>
<div class="web-big-padding-section-level-2">
<section
class="web-container web-u-padding-block-0"
style="--container-size:78.75rem"
>
<div class="u-cross-child-end">
<p class="web-description">
Build your entire backend within minutes and scale effortlessly using
Appwrite's open-source platform. Add Authentication, Databases,
Functions, Storage, and Messaging to your projects using the frameworks
and languages of your choice.
</p>
<a
href="https://cloud.appwrite.io"
class="web-button is-full-width-mobile u-margin-block-start-32"
>
<span class="text">Get started</span>
</a>
</div>
</section>
</div>
<div class="web-big-padding-section-level-2">
<section
class="web-container web-u-padding-block-0"
@@ -132,12 +152,8 @@
<Products />
<ProductsMobile />
<div
class="web-big-padding-section-level-1 web-white-section light relative"
>
<div
class="u-inset-block-end-0 u-inset-inline-start u-width-full-line absolute"
>
<div class="web-big-padding-section-level-1 web-white-section light relative">
<div class="u-inset-block-end-0 u-inset-inline-start u-width-full-line absolute">
<img
class="u-width-full-line block"
src="/images/bgs/padding-section-1.svg"
@@ -154,9 +170,8 @@
Self-host your data or take it to the Cloud
</h2>
<p class="web-description u-max-width-700">
Migrate your data from and to any platform at any time with
Appwrite Migrations. With built-in security and privacy for peace
of mind.
Migrate your data from and to any platform at any time with Appwrite
Migrations. With built-in security and privacy for peace of mind.
</p>
</section>
<div class="web-u-margin-block-start-80 overflow-hidden">
@@ -219,8 +234,7 @@
/>
<h3 class="aw-info-boxes-title">GDPR</h3>
<p class="aw-info-boxes-content">
Safeguard user data and privacy with provided GDPR
regulations.
Safeguard user data and privacy with provided GDPR regulations.
</p>
</li>
<li class="web-info-boxes-item">
@@ -271,8 +285,8 @@
icon="product-hunt"
avatarSrc="/images/community/avatars/terry.png"
>
Been a huge supporter of Appwrite for over a year, championing
it even at the companies I was working at. Their community is
Been a huge supporter of Appwrite for over a year, championing it
even at the companies I was working at. Their community is
second-to-none, speed of feature release is exceptional, and the
support in their Discord is incredible.
</DeveloperCard>
@@ -285,9 +299,9 @@
avatarSrc="/images/community/avatars/varun.png"
>
Recently, I embarked on a journey to create a Real-Time Chat
Application that would redefine seamless communication. Along
the way, I discovered an incredible tool that transformed my
backend game - Appwrite!
Application that would redefine seamless communication. Along the
way, I discovered an incredible tool that transformed my backend
game - Appwrite!
</DeveloperCard>
</li>
<li>
@@ -298,14 +312,13 @@
avatarSrc="/images/community/avatars/kap.png"
>
Backend Engineers, you will agree with me that building the
authentication process for your app with each new API
development is a pain. Here's my secret: I let <a
authentication process for your app with each new API development is
a pain. Here's my secret: I let <a
href="https://twitter.com/appwrite"
target="_blank"
rel="noopener noreferrer"
class="web-link is-inline">@appwrite</a
> handle my authentication process while I focus on the business
logic.
> handle my authentication process while I focus on the business logic.
</DeveloperCard>
</li>
<li>
@@ -326,10 +339,10 @@
icon="product-hunt"
avatarSrc="/images/community/avatars/terieyenike.png"
>
I have used Appwrite twice, and the experience of using it was
great as I got to build a full-stack application. I would gladly
recommend it to anyone looking to explore an alternative
database option. Appwrite is simply the best.
I have used Appwrite twice, and the experience of using it was great
as I got to build a full-stack application. I would gladly recommend
it to anyone looking to explore an alternative database option.
Appwrite is simply the best.
</DeveloperCard>
</li>
<li>
@@ -346,8 +359,8 @@
rel="noopener noreferrer"
class="web-link is-inline">@appwrite</a
>. With its robust feature set and open-source nature, it's the
perfect choice for developers who want to build secure and
scalable applications.
perfect choice for developers who want to build secure and scalable
applications.
</DeveloperCard>
</li>
</ul>
@@ -380,8 +393,8 @@
Code the way you want
</h2>
<p class="web-description u-max-width-600">
We support many SDKs making Appwrite flexible to your needs and
ensuring you can code with the language you want at any time.
We support many SDKs making Appwrite flexible to your needs and ensuring
you can code with the language you want at any time.
</p>
<Technologies />
<a
@@ -401,11 +414,7 @@
style:height="100%"
style:left="0"
>
<div
style:display="grid"
style:place-items="center"
style:height="100%"
>
<div style:display="grid" style:place-items="center" style:height="100%">
<img
src="/images/bgs/diagonal-lines.png"
alt=""

View File

@@ -1,33 +1,33 @@
<script lang="ts">
import { visible } from "$lib/actions";
import TocNav from "$lib/components/TocNav.svelte";
import TocRoot from "$lib/components/TocRoot.svelte";
import { Main } from "$lib/layouts";
import { visible } from '$lib/actions';
import TocNav from '$lib/components/TocNav.svelte';
import TocRoot from '$lib/components/TocRoot.svelte';
import { Main } from '$lib/layouts';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from "$lib/utils/metadata";
import { TITLE_SUFFIX } from "$routes/titles";
import FooterNav from "../../lib/components/FooterNav.svelte";
import MainFooter from "../../lib/components/MainFooter.svelte";
import Copy from "./Copy.svelte";
import { DEFAULT_HOST } from '$lib/utils/metadata';
import { TITLE_SUFFIX } from '$routes/titles';
import FooterNav from '../../lib/components/FooterNav.svelte';
import MainFooter from '../../lib/components/MainFooter.svelte';
import Copy from './Copy.svelte';
const title = "Assets" + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const ogImage = DEFAULT_HOST + "/images/open-graph/website.png";
const title = 'Assets' + TITLE_SUFFIX;
const description =
'Resources for presenting the Appwrite brand, ensuring consistency in using our logos, colours, and other brand elements across various platforms and materials.';
const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
enum Section {
NAMING = "Naming",
LOGOTYPE = "Logotype",
LOGOMARK = "Logomark",
COLORS = "Brand colors",
VISUALS = "Product visuals",
CONTACT = "Contact us",
NAMING = 'Naming',
LOGOTYPE = 'Logotype',
LOGOMARK = 'Logomark',
COLORS = 'Brand colors',
VISUALS = 'Product visuals',
CONTACT = 'Contact us'
}
const getSectionId = (section: Section) =>
section.toLowerCase().replace(/\s/g, "-");
const getSectionId = (section: Section) => section.toLowerCase().replace(/\s/g, '-');
let selectedMap: Map<Section, boolean> = new Map(
Object.values(Section).map((section) => [section, false]),
Object.values(Section).map((section) => [section, false])
);
const handleVisibility = (section: Section) => {
@@ -79,23 +79,16 @@
</button>
</header>
<TocNav />
<main
class="web-grid-120-1fr-auto-main /web-is-mobile-closed"
id="main"
>
<main class="web-grid-120-1fr-auto-main /web-is-mobile-closed" id="main">
<div class="web-content">
<section>
<p>
Resources for presenting the Appwrite brand to maintain
consistency while using our logos, colors, and other brand
elements across various platforms and materials.
Resources for presenting the Appwrite brand to maintain consistency
while using our logos, colors, and other brand elements across
various platforms and materials.
</p>
<a
href="/assets.zip"
download
class="web-button u-cross-child-start"
>
<a href="/assets.zip" download class="web-button u-cross-child-start">
<span class="web-icon-download" aria-hidden="true" />
<span>Download assets</span>
</a>
@@ -111,9 +104,9 @@
Naming
</h2>
<p>
Write 'Appwrite,' with a lowercase 'w' and no space between
the two words. Please refrain from using variations like
'AppWrite' or 'App Write'.
Write 'Appwrite,' with a lowercase 'w' and no space between the
two words. Please refrain from using variations like 'AppWrite'
or 'App Write'.
</p>
</div>
</section>
@@ -129,8 +122,8 @@
</h2>
<p>
The Appwrite logo stands as a prominent symbol of our brand's
identity. Refrain from altering our logo and preferably use
our logo on a neutral background.
identity. Refrain from altering our logo and preferably use our
logo on a neutral background.
</p>
<div
class="web-u-flex-vertical-mobile u-margin-block-start-12 flex flex-wrap gap-8"
@@ -150,7 +143,10 @@
href="/assets/logotype/white.svg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>SVG</span>
</a>
<a
@@ -158,7 +154,10 @@
href="/assets/logotype/white.png"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -178,7 +177,10 @@
href="/assets/logotype/black.svg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>SVG</span>
</a>
<a
@@ -186,7 +188,10 @@
href="/assets/logotype/black.png"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -227,8 +232,8 @@
</h3>
<p>
While prioritizing recognizability, the logotype is the
recommended choice. Using the Appwrite logomark is suitable
for situations where space constraints make it challenging to
recommended choice. Using the Appwrite logomark is suitable for
situations where space constraints make it challenging to
showcase the complete logotype.
</p>
<div
@@ -249,7 +254,10 @@
href="/assets/logomark/logo.svg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>SVG</span>
</a>
<a
@@ -257,7 +265,10 @@
href="/assets/logomark/logo.png"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -277,7 +288,10 @@
href="/assets/logomark/logo.svg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>SVG</span>
</a>
<a
@@ -285,7 +299,10 @@
href="/assets/logomark/logo.png"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -373,9 +390,7 @@
Use these product visuals to enhance your articles,
presentations, and content related to Appwrite.
</p>
<div
class="grid-cols-2-opt-2 u-margin-block-start-12 grid gap-8"
>
<div class="grid-cols-2-opt-2 u-margin-block-start-12 grid gap-8">
<div class="media-wrapper">
<img
class="web-u-border-radius-8 web-u-media-ratio-16-9 u-width-full-line"
@@ -388,15 +403,21 @@
href="/assets/visuals/dashboard.jpg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>JPG</span>
</a>
<a
class="web-button is-secondary"
href={"/assets/visuals/dashboard.png"}
href={'/assets/visuals/dashboard.png'}
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -413,15 +434,21 @@
href="/assets/visuals/auth.jpg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>JPG</span>
</a>
<a
class="web-button is-secondary"
href={"/assets/visuals/auth.png"}
href={'/assets/visuals/auth.png'}
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -438,15 +465,21 @@
href="/assets/visuals/databases.jpg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>JPG</span>
</a>
<a
class="web-button is-secondary"
href={"/assets/visuals/databases.png"}
href={'/assets/visuals/databases.png'}
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -464,15 +497,21 @@
href="/assets/visuals/storage.jpg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>JPG</span>
</a>
<a
class="web-button is-secondary"
href={"/assets/visuals/storage.png"}
href={'/assets/visuals/storage.png'}
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -490,15 +529,21 @@
href="/assets/visuals/functions.jpg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>JPG</span>
</a>
<a
class="web-button is-secondary"
href={"/assets/visuals/functions.png"}
href={'/assets/visuals/functions.png'}
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>
@@ -515,15 +560,21 @@
href="/assets/visuals/messaging.jpg"
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>JPG</span>
</a>
<a
class="web-button is-secondary"
href={"/assets/visuals/messaging.png"}
href={'/assets/visuals/messaging.png'}
download
>
<span class="web-icon-download" aria-label="download" />
<span
class="web-icon-download"
aria-label="download"
/>
<span>PNG</span>
</a>
</div>

View File

@@ -2,14 +2,14 @@
import { Main } from '$lib/layouts';
import { MainFooter, FooterNav, Article } from '$lib/components';
import { TITLE_SUFFIX } from '$routes/titles.js';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { DEFAULT_HOST } from '$lib/utils/metadata';
export let data;
const featured = data.posts.find((post) => post.featured);
const title = 'Blog' + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const description = 'Stay updated with the latest product news, insights, and tutorials from the Appwrite team. Discover tips and best practices for hassle-free backend development.';
const ogImage = DEFAULT_HOST + '/images/open-graph/blog.png';
</script>

View File

@@ -1,7 +1,7 @@
---
layout: post
title: How Pink Design helped us improve web accessibility in our products.
description:
description: Appwrites open-source UI library drastically improved our web accessibility.
date: 2022-11-14
cover: /images/pages/homepage/dashboard.png
timeToRead: 3

View File

@@ -0,0 +1,136 @@
---
layout: post
title: "Announcing Appwrite's new Integrations Catalog"
description: We are beyond excited to announce the launch of our brand-new Appwrite Integrations Catalog.
date: 2024-07-29
cover: /images/blog/integrations-catalog.png
timeToRead: 12
author: aditya-oberai
category: product
featured: true
---
Our new Integrations Catalog is designed to empower you by providing a seamless way to integrate your favorite tools, libraries, and services with Appwrite, making your development process even more efficient and enjoyable.
# One-stop shop for all your integrations
Youre building your next big project on top of Appwrite; your backend is all set up and ready to go to production. But then you realize you need a way to sell subscriptions and send emails, and youve decided at the last minute you want to add more OAuth2 providers. Imagine you had to build all these integrations for your app from scratch in a short space of time. With the new [Integrations Catalog](https://appwrite.io/integrations), we have done the heavy lifting for you. Youll find integrations for both Cloud and Self-hosted that cater to every aspect of your development needs, allowing you to build your app exactly as you intended.
# Whats inside the Appwrite Integrations Catalog?
Weve bundled all integrations into different categories. Here are a few notable providers (with many more to come!). Check out the full catalog on the Integrations page.
## Authentication
- [Phone auth](https://appwrite.io/docs/products/auth/phone-sms)
Phone auth allows you to authenticate users using One-Time Passwords (OTPs) sent to their mobile phones via SMS, making it a highly-convenient passwordless alternative to email-password authentication. You can use Twilio to enable phone authentication for your apps.
- [OAuth2](https://appwrite.io/docs/products/auth/oauth2)
You can set up OAuth2 with over 30 providers. OAuth is a way for apps to request limited access to a user's account on another service without needing the user's password. This keeps the users account more secure while making signing up and logging in all the more convenient.
Some of Appwrites OAuth integrations include Amazon, Appwrite, Discord, Google, and Notion.
## Deployments
- [GitHub](https://appwrite.io/docs/advanced/self-hosting/functions)
We've integrated GitHub to simplify your development workflow with Appwrite Functions. This integration enables the generation of repositories for function templates and manages automatic deployments for any Appwrite Functions through GitHub.
## Messaging
- [Twilio](https://appwrite.io/docs/products/messaging/twilio) for SMS
You can use the Twilio provider in Appwrite Messaging to send customized SMS messages to your users. Whether you need to send them instantly or schedule them for later, these messages can serve a variety of purposes like reminders, promotions, announcements, and even custom authentication flows.
- [Sendgrid](https://appwrite.io/docs/products/messaging/sendgrid) for Email
Send custom emails to your users with Sendgrid, either instantly or on a schedule. Use it to deliver reminders, promotions, and announcements, keeping your audience engaged and informed.
- [APNs and FCM](https://appwrite.io/docs/products/messaging/send-push-notifications) for Push notifications
Use Apple Push Notifications service (APNs) or Firebase Cloud Messaging to send in-app or push notifications. Deliver app updates, promotional offers, and other messages straight to your users devices.
- [Vonage](https://appwrite.io/docs/products/messaging/vonage) for WhatsApp messages
Going one step further? Use Vonage to send WhatsApp messages and connect with your users in a modern, user-friendly way.
## Storage
- Amazon S3
Store your files on self-hosted instances with Amazon S3. Amazon S3 provides scalable object storage that allows you to manage and access your data seamlessly, ensuring high availability and durability.
## Logging
Monitor your application's performance by tracing errors across your Appwrite instance and fixing them faster. These tools help you proactively manage issues and deliver a more stable experience:
- Sentry
- Raygun
- AppSignal
## AI
- Hugging Face and Generative AI
Enhance your app with AI through Appwrite's integrations. Build [with our AI function templates](https://appwrite.io/blog/post/building-with-ai-function-templates) from popular tools like Hugging Face, OpenAI, Perplexity, and more. Imagine creating [your very own AI chatbot](https://appwrite.io/blog/post/personal-chatbot-gpt-4o) with OpenAIs GPT-4o — it's easier than you think!
## Payments
- Stripe
Use Stripe to set up app [subscriptions](https://appwrite.io/docs/tutorials/subscriptions-with-stripe/step-1) and payments. It's designed to be straightforward so you can smoothly manage your transactions.
- Lemon Squeezy
Lemon Squeezy lets you set up payments and subscriptions quickly, so you can focus on your apps functionality. Check out [this video for a step-by-step guide](https://www.youtube.com/watch?v=dHo7lvpU6gs).
## Databases
- MongoDB Atlas and Upstash Vector
Easily manage your data using MongoDB Atlas and Upstash Vector integration. MongoDB Atlas offers a flexible database solution, and Upstash Vector improves query capabilities for fast and reliable data access. Together, they help you manage data efficiently and boost your apps performance.
## Search
- Algolia
Improve your apps search functionality with the Algolia integration. Algolia makes it straightforward to integrate practical search features, helping users easily find the information they need without hassle.
# Designed with your experience in mind
As with everything we do here at Appwrite, we heavily focus on the developer experience. Our main goal with the Integration Catalog is to meet your needs when integrating X with Appwrite. We focused on a set of principles that helped us deliver on our promise:
1. Appwrite developers need quick access to integration options, including everything provided in the console and future integrations.
2. Categories should group integrations, and a consistent hierarchy of information should exist on every page.
3. Finding new categories should be logical, intuitive, and fast.
4. The content should be presented in an easy-to-digest manner and help you find what youre looking for.
Missing anything? Have feedback? Let us know on [Discord](https://appwrite.io/discord)!
# Become a Technology Partner
With the launch of our Integrations Catalog, were also inviting developers and companies to join us as **Technology Partners**. This is your chance to integrate your solutions with Appwrite, reach a wider audience, and add value to the developer community.
## Why become a Technology Partner?
- **Improve dev experience:** Improve the experience by collaborating on an integration.
- **Increased exposure**: Feature your integration in front of our growing community of developers.
- **Collaborative marketing**: Partner with us on co-marketing efforts to highlight your integration.
- **Dedicated developer support**: Get assistance from our team to ensure your integration is top-notch.
- **Exclusive developer tools**: Access our API documentation, SDKs, and best practices to make your integration seamless.
# How to apply
Do you think your tool plays well with Appwrite? Visit our [Integrations Catalog Technology partners page](https://appwrite.io/integrations/technology-partner) and fill out the submission form. Tell us about your company, the integration youre proposing, and how it benefits developers using Appwrite. Our team will review your submission and get back to you with the next steps.
# More to come
We believe the Appwrite [Integrations Catalog](https://appwrite.io/integrations) will open up new possibilities for developers, making it easier than ever to build, connect, and deploy applications with Appwrite. Watch for updates on our changelog and socials as we add more integrations.
# Resources
- [Join us on discord](https://appwrite.io/discord)
- [Visit our documentation](https://appwrite.io/docs)
- [Get started with Appwrite](https://cloud.appwrite.io/)

View File

@@ -1,7 +1,7 @@
---
layout: post
title: "Announcing Messaging: Push, Email and SMS directly from your Appwrite backend"
description:
description: You can now send emails, SMS and push notifications with Appwrites easy-to-use APIs.
date: 2024-02-26
cover: /images/blog/messaging-announcement.png
timeToRead: 6

View File

@@ -7,7 +7,7 @@ cover: /images/blog/ai-announcement.png
timeToRead: 5
author: christy-jacob
category: AI
featured: true
featured: false
---
The AI hype is real and will be around for many years to come. In 2021 alone, AI startups worldwide raised nearly $50 billion in venture capital across approximately 1,500 deals, reflecting a significant increase from previous years. So it's no surprise that many of you are looking to build AI powered applications. But that's easier said than done, as building AI powered applications can be tricky. We don't want it to be. That's why we're happy to share multiple AI related announcements designed to enhance the Appwrite experience and adapt to new possibilities for devs building with Appwrite.

View File

@@ -0,0 +1,192 @@
---
layout: post
title: "Integrate Twilio, SendGrid, APNs and FCM into your Appwrite project"
description: Which messaging provider should you choose for your app?
date: 2024-07-30
cover: /images/blog/integrations-messaging/cover.png
timeToRead: 6
author: aditya-oberai
category: product
featured: false
---
Bringing messaging into your app — emails, push notifications, or SMS — gives your users a direct line to you. It lets you instantly share updates, reminders, special offers, or important info right when your users need it, keeping them engaged. But which messaging provider do you choose, and how do you integrate it?
In this article, we cover the benefits of multiple messaging providers to help you choose the best one for your use case. We will also guide you through integrating Twilio, SendGrid, APNs, and FCM into your app using Appwrite.
# Prerequisites
Before we begin, you must sign up for [Appwrite Cloud](https://cloud.appwrite.io/register) and create a project if you havent already. Signing up is free and should only take a few minutes.
# Twilio
Twilio is a cloud communications platform that offers SMS, voice, video, and email services. It's known for its flexibility, scalability, and ease of integration. As part of its comprehensive communication tools, Twilio also provides a robust push notification service.
**Benefits of using Twilio:**
- **Multi-channel support**: Manage SMS, MMS, email, and push notifications from one platform.
- **Cross-platform messaging**: Send push notifications to both iOS and Android devices easily.
- **Personalization and segmentation**: Customize messages for targeted communication.
- **Scheduling and automation**: Schedule and automate notifications based on user actions or set conditions.
**Best use cases:**
- **Customer support:** Use SMS and voice for timely customer service.
- **Marketing campaigns:** Send personalized promotions and updates.
- **App engagement:** Push notifications for app updates, reminders, and special offers.
- **Event reminders:** Schedule automated reminders for appointments and events.
# How to integrate Twilio into your app
Integrating Twilio into your app is fairly simple. For the purposes of this tutorial, well focus on the SMS functionality.
## Step 1. Set up a Twilio account
Create a [Twilio account](https://www.twilio.com/try-twilio) and purchase a phone number that supports SMS. Go to **Account info** and save your **Account SID** and **Account Token**, which you will need for the next step.
## Step 2: Add Twilio provider to your Appwrite project
In your Appwrite project, navigate to **Messaging** > **Providers** > **Create a provider** > **SMS**. Name your provider and select **Twilio**. On the next page, fill out the **Account SID** and **Account Token**, as well as the phone number that will be sending SMS.
![Twilio messaging integration](/images/blog/integrations-messaging/1.png)
Once you complete provider creation, you should see it on your list of providers. You can now use this number to send SMS to your users!
## Step 3: Test the provider
In your **Messaging** tab, you can now create a new message. Pick your users ([set up an SMS authentication flow to get users phone numbers if you havent yet](/docs/products/auth/phone-sms)), set your target and topic and choose the time. Thats it — now your users will receive an SMS.
Visit the [docs](https://appwrite.io/docs/products/messaging/twilio) for a more detailed tutorial or get started with Twilio right away on the [integrations page.](https://appwrite.io/integrations)
# SendGrid
SendGrid is a reliable email delivery service that helps businesses send emails quickly and efficiently. SendGrid promises a 99% deliverability rate and ensures your emails land in the inbox, not the spam folder, which is crucial for maintaining good communication with your customers.
**Benefits of using SendGrid:**
- **High deliverability:** SendGrid ensures your emails get delivered to the inbox, improving engagement rates.
- **Detailed analytics:** Gain insights into email performance with analytics and reporting.
- **Scalability:** Whether you're sending a few emails or millions, SendGrid scales to meet your needs.
**Best use cases:**
- **Newsletters:** Keep your audience informed with regular updates and news.
- **Promotional emails:** Drive sales and engagement with targeted marketing campaigns.
- **Transactional emails:** Send important notifications like order confirmations, shipping updates, and password resets.
# How to integrate SendGrid into your app
Follow these simple steps to integrate SendGrid into your Appwrite project.
## Step 1: Sign up on SendGrid
First, [sign up for a SendGrid account](https://signup.sendgrid.com/) and complete the setup. Then, [create an API key](https://www.twilio.com/docs/sendgrid/ui/account-and-settings/api-keys) with full access and save it for future use. Next, follow SendGrid's [Domain Authentication](https://www.twilio.com/docs/sendgrid/ui/account-and-settings/how-to-set-up-domain-authentication) guide to authenticate your domain. If you dont have a domain, use their [Single Sender Verification](https://www.twilio.com/docs/sendgrid/ui/sending-email/sender-verification) process to verify your sender identity.
## Step 2: Add SendGrid provider to your Appwrite project
In your Appwrite project, go to **Messaging** > **Providers** > **Create a provider** > **Email.** Name your provider and choose SendGrid. In the next page, you get to enter the API Key, the email address and customize the sender name, reply-to email and name.
![SendGrid messaging integration](/images/blog/integrations-messaging/2.png)
## Step 3: Test the SendGrid provider
Make sure you have at least one [topic](https://appwrite.io/docs/products/messaging/topics) or [target](https://appwrite.io/docs/products/messaging/targets) set up before testing.
Once the provider is configured, head to **Messages** > **Create an email message**. Enter the text, choose the recipients, and set the delivery time for your message. Thats it — you can now send emails to your users!
Visit the [docs](https://appwrite.io/docs/products/messaging/sendgrid) for a more detailed tutorial or start with SendGrid in the [Integrations Catalog.](https://appwrite.io/integrations)
# APNs
APNs (Apple Push Notification Service) is an Apple tool that lets you send notifications straight to iOS devices. It helps you keep your users updated and engaged with your app in real time.
**Benefits of using APNs:**
- **Instant alerts:** Notify users right away with important updates.
- **Rich content:** Include images, videos, and interactive elements in your notifications.
- **Boost engagement:** Keep users coming back with personalized messages.
**Best use cases:**
- **App updates:** Inform users about new features or important changes.
- **Reminders:** Send reminders for appointments, tasks, or events.
- **Special offers:** Share promotions and special deals.
# How to integrate APNs into your app
Follow these simple steps to integrate APNs into your Appwrite project.
## Step 1: Sign up for Apple Developer
First, [sign up for the Apple Developer program](https://developer.apple.com/programs).
Head to your new Apple Developer account and save the following details:
| Field name | |
| --- | --- |
| Bundle ID | Head to Apple Developer account > Program resources > Certificates, Identifiers & Profiles > Identifiers |
| Team ID | Head to Apple Developer account > Membership details > Team ID |
| Authentication key (.p8 file) | Head to Apple Developer account > Program resources > Certificates, Identifiers & Profiles > Keys. Create a key and give it a name. Enable the Apple Push Notifications service (APNS), and register your key. |
| Authentication key ID | Head to Apple Developer account > Program resources > Certificates, Identifiers & Profiles > Keys. Click on your key to view details. |
## Step 2: Add APNs provider to your Appwrite project
In your Appwrite project, go to **Messaging** > **Providers** > **Create a new push notifications provider**.
Enter the **team ID**, **bundle ID**, **authentication key ID**, and the **authentication key (.p8 file)** you got from the Apple Developer Member Center. If your app uses a development provisioning profile, enable Sandbox mode.
![APNs messaging integration](/images/blog/integrations-messaging/3.png)
## Step 3: Test the provider
To test the provider on your Apple devices, you'll need to make some additional settings in Xcode. Open your app in **Xcode** > **Signing & Capabilities** > **Capabilities** > **Push Notifications**, and turn it on.
Next, follow the [Send push notifications](https://appwrite.io/docs/products/messaging/send-push-notifications) guide to test your setup. After that, you should be able to send Push notifications from **Messaging**.
Visit the [docs](https://appwrite.io/docs/products/messaging/apns) for a more detailed tutorial or get started with APN in the [Integrations Catalog.](https://appwrite.io/integrations)
## FCM
FCM (Firebase Cloud Messaging) is a cross-platform messaging solution that lets developers send notifications to Android, iOS, and web applications. Its an efficient way to reach users on multiple platforms with a single service.
**Benefits of using FCM:**
- **Multi-platform:** Reach users on Android, iOS, and the web.
- **Flexible messaging:** Send notifications or data messages for various needs.
- **Track performance:** Use Firebase Analytics to see how your messages are doing.
**Best use cases:**
- **User engagement:** Send personalized notifications to keep users interested.
- **Real-time updates:** Push updates on live activities, like scores in a sports app or breaking news.
- **Special offers:** Share promotions and special deals.
# How to integrate FCM into your app
Follow these simple steps to integrate FCM into your Appwrite project.
## Step 1: Sign up on Firebase
[Create a Firebase account](https://firebase.google.com/) and set up a new project. Go to **Project settings > Service accounts to generate a new private key.** Then, download the JSON file that comes with it.
To enable FCM, go to **Cloud Messaging** > Click the three-dots menu > **Enable**.
## Step 2: Add FCM provider to your Appwrite project
In your Appwrite **Messaging** page, click on the **Providers** tab > **Create a new push notifications provider**.
Select **FCM** and upload the JSON file.
![FCM messaging integration](/images/blog/integrations-messaging/4.png)
## Step 3: Test the provider
To test the provider on mobile apps, you must do additional configuration steps for both iOS and Android. You can find a detailed tutorial in the [docs](https://appwrite.io/docs/products/messaging/fcm). Just like with APN, once youre done with the testing stage, you can start sending notifications from your **Messaging** tab.
# More resources
By now, you should be able to integrate your chosen messaging provider and start connecting with your users. If youre still searching for the right solution, take a look at our [Integrations Catalog](https://appwrite.io/integrations) for a comprehensive list of messaging providers. You can also find additional resources below to help you set up messaging effectively.
- [Push notifications best practices](https://appwrite.io/blog/post/push-notifications-best-practices).
- [Messaging explained](https://appwrite.io/blog/post/messaging-explained).
- [Messaging in Appwrite docs.](https://appwrite.io/docs/products/messaging)

View File

@@ -0,0 +1,106 @@
---
layout: post
title: "July product update: Integrations Catalog | daily.dev Squad | FreeCodeCamp"
description: "Check out everything that happened in July in your monthly Appwrite digest."
date: 2024-08-01
cover: /images/blog/product-update-july/cover.png
timeToRead: 8
author: dennis-ivy
category: product
---
July was packed with announcements and new content. We announced Appwrite integrations, started a [daily dev](http://daily.dev) Squad, and created a bunch of coding tutorials for you. Lets get straight into it!
# Integrations Catalog
![Integrations catalog](/images/blog/product-update-july/1.png)
We just launched our brand new Integrations Catalog — a one-stop-shop for all your Appwrite integrations needs. Its designed to:
- Give you quick access to all Appwrite integrations
- Provide easy-to-follow implementation guides
- Store all integrations in one place with an intuitive design
The current integrations are just the first of many. Well be continually updating and adding more, so stay tuned!
[Read the announcement.](https://apwr.dev/integrate)
# [daily.dev](http://daily.dev) Squad
![dailydev squad](/images/blog/product-update-july/2.png)
Appwrite now has a Squad on [daily.dev](http://daily.dev) and youre invited!
A Squad is an easy way to keep up with all the cool things happening at Appwrite and get useful engineering resources in your daily digest. Plus, you can participate in discussions on tech trends and best practices with fellow Appwriters and share your knowledge and expertise.
[Join the Appwrite Squad now.](https://apwr.dev/dailydev)
# Appwrite at FreeCodeCamp
![FreeCodeCamp video](/images/blog/product-update-july/3.png)
Appwrite developed a coding course on the [FreeCodeCamp.org](http://FreeCodeCamp.org) YouTube channel. FreeCodeCamp is a popular learning resource for developers, with hundreds of easy-to-follow video guides and tutorials.
[Learn how to create a full-stack sticky notes app using JavaScript and Appwrite in this video tutorial.](https://www.youtube.com/watch?v=yBThHM2pBbE)
---
# Bug fixes and improvements
- Small fixes to the migrations flows in the console to bring a better migrations experience
- PR [#1132](https://github.com/appwrite/website/pull/1132), [#1133](https://github.com/appwrite/website/pull/1133), [#1134](https://github.com/appwrite/website/pull/1134): Improved SendGrid docs
- PR [#1226](https://github.com/appwrite/console/pull/1226): User preferences removal bug
- PR [#1232](https://github.com/appwrite/console/pull/1232): Update bundle ID field to services ID in Apple OAuth adapter
- PR [#1190](https://github.com/appwrite/console/pull/1190): Add theme on initial load
- PR [#1188](https://github.com/appwrite/console/pull/1188): Fix redirect password recovery
---
# Community recognitions
This month, were excited to feature Daniel Veremchuk as part of our Monthly Community Recognitions.
Daniel developed the new Appwrite Hono Adapter for Bun as part of his Appwrite adapter repository. This adapter allows you to run your Hono application on Appwrite's **`bun-1.0+`** runtime.
[Take a look at the Bun adapter](https://www.npmjs.com/package/@gravlabs/appwrite-hono-adapter-bun).
If you'd like to participate in next month's Community Recognitions, [join our Discord server](https://appwrite.io/discord) to showcase your project.
---
# Built with Appwrite
AyeHigh is a suite of user-friendly Gen AI tools designed to help improve resumes for students and young professionals. The developer, Raj Savaliya, leveraged Appwrites Auth, Storage and Databases to build the apps backend faster. Heres what he says about it:
> Fully able to focus on business logic without spending time on developing backend, auth, storage and all that stuff from scratch. Saved a lot of time and shipped faster.
>
AyeHigh was also recently featured on ProductHunt. [Check them out here](https://www.producthunt.com/products/ayehigh#ayehigh).
---
# Engineering resources
- [Watch](https://www.youtube.com/watch?v=lEflo_sc82g): Build and deploy a patient management system with Next.js
- [Read](https://appwrite.io/blog/post/set-up-google-auth-appwrite-react): How to set up Google authentication in React with Appwrite
- [Read](https://appwrite.io/blog/post/how-to-build-a-remote-tech-stack): How to build a tech stack for a remote startup
- [Read](https://appwrite.io/blog/post/rest-vs-graphql-websockets-which-is-best-for-your-app): REST vs GraphQL vs WebSockets: which is best for your app?
- [Read](https://appwrite.io/blog/post/handle-cors-in-serverless-functions): How to handle CORS in Appwrite serverless functions
- [Read](https://appwrite.io/blog/post/messaging-explained): Messaging explained
- [Read:](https://appwrite.io/blog/post/how-to-attract-users-to-open-source-project) How to attract contributors and users to your open source project
# Open source and community updates
- [Repository:](https://github.com/ItzNotABug/web-amp) Appwrite Messaging method parameters on JS/Node SDKs by [Darshan](https://github.com/ItzNotABug)
- [Blog post:](https://devpost.com/software/vrtuhub-ltd) Vrtuhub — a hackathon project built with Appwrites backend
---
# Whats to come
July has come to an end, but August is a big month here at Appwrite!
- Init is coming soon…
- New and exciting features will be launched
- And we have new Cloud regions in the works!
Follow us on [X](https://x.com/appwrite) and check our [Changelog](https://appwrite.io/changelog) regularly, as we will release more information in the coming weeks.

View File

@@ -16,7 +16,7 @@ All it took to lose interest was the giant form I had to fill out to add a recei
With over [30+ apps installed on a typical user's phone](https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/average-number-of-apps-on-smartphones/)
on average, fighting for engagement and retention is tougher than ever.
Users are sensitive to friction, with a reported 50% of users [opting for new online merchants just for lowered friction](https://www.pwc.co.uk/industries/documents/frictionless-retail-the-future-of-shopping.pdf)
and Shoppify reporting [low-friction payment methods and flows can lead to >50% increase in conversion](https://web-assets.bcg.com/e4/0c/a1acfc2a4e52a029cb37c6fe83ba/bcg-leading-online-shoppers-to-the-finish-line-june-2023.pdf).
and Shopify reporting [low-friction payment methods and flows can lead to >50% increase in conversion](https://web-assets.bcg.com/e4/0c/a1acfc2a4e52a029cb37c6fe83ba/bcg-leading-online-shoppers-to-the-finish-line-june-2023.pdf).
No one has time to fill out giant forms.
To help you and your users avoid filling out giant forms, we're going to build a simple receipt processing endpoint with Appwrite

View File

@@ -0,0 +1,14 @@
---
layout: changelog
title: "Announcing Appwrite's new Integrations Catalog"
date: 2024-07-30
cover: /images/changelog/2024-07-30.png
---
We are beyond excited to announce the launch of our brand-new Appwrite Integrations Catalog.
This catalog is designed to empower you by providing a seamless way to integrate your favorite tools, libraries, and services with Appwrite, making your development process even more efficient and enjoyable.
{% arrow_link href="/blog/post/announcing-appwrite-integration-catalog" %}
Read the announcement to learn more
{% /arrow_link %}

View File

@@ -2,7 +2,7 @@
import { goto } from '$app/navigation';
import { FooterNav, MainFooter, PreFooter } from '$lib/components';
import { Main } from '$lib/layouts';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { DEFAULT_HOST } from '$lib/utils/metadata';
import { onMount } from 'svelte';
import ChangelogEntry from '../ChangelogEntry.svelte';
import { page } from '$app/stores';
@@ -13,7 +13,7 @@
const seo = {
title: 'Changelog' + TITLE_SUFFIX,
description: DEFAULT_DESCRIPTION,
description: 'Check out our detailed changelog to see what\'s new and what updates have been made to Appwrite Cloud and Self Hosted.',
ogImage: `${DEFAULT_HOST}/images/open-graph/website.png`
};

View File

@@ -52,7 +52,7 @@
import PreFooter from '$lib/components/PreFooter.svelte';
import { GITHUB_STARS } from '$lib/constants';
import { Main } from '$lib/layouts';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { DEFAULT_HOST } from '$lib/utils/metadata';
import { TITLE_SUFFIX } from '$routes/titles';
import type { EventCardProps } from './EventCard.svelte';
import EventCard from './EventCard.svelte';
@@ -122,7 +122,7 @@
}
const title = 'Community' + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const description = 'Join our vibrant community of developers. Ask questions, contribute solutions, and inspire others to improve the backend development experience.';
const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
</script>

View File

@@ -1,6 +1,7 @@
---
layout: policy
title: Cookies Policy
description: Read our cookie policy to understand your choices and manage your preferences.
transparentTableCells: true
---

View File

@@ -1,48 +1,49 @@
<script lang="ts">
import { Carousel } from "$lib/components";
import Technologies from "$lib/components/Technologies.svelte";
import Docs from "$lib/layouts/Docs.svelte";
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from "$lib/utils/metadata";
import { TITLE_SUFFIX } from "$routes/titles";
import MainFooter from "../../lib/components/MainFooter.svelte";
import CodeCard, { type CodeCardProps } from "./CodeCard.svelte";
import Sidebar from "./Sidebar.svelte";
import { Carousel } from '$lib/components';
import Technologies from '$lib/components/Technologies.svelte';
import Docs from '$lib/layouts/Docs.svelte';
import { DEFAULT_HOST } from '$lib/utils/metadata';
import { TITLE_SUFFIX } from '$routes/titles';
import MainFooter from '../../lib/components/MainFooter.svelte';
import CodeCard, { type CodeCardProps } from './CodeCard.svelte';
import Sidebar from './Sidebar.svelte';
const title = "Docs" + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const ogImage = DEFAULT_HOST + "/images/open-graph/docs.png";
const title = 'Docs' + TITLE_SUFFIX;
const description =
'Learn how to build like a team of hundreds. Get started with Authentication, Databases, Storage, Functions, and Messaging in your preferred framework.';
const ogImage = DEFAULT_HOST + '/images/open-graph/docs.png';
const tutorials: CodeCardProps[] = [
{
href: "/docs/tutorials/react",
cover: "/images/tutorials/react.png",
title: "React tutorial",
description: "Learn Appwrite Auth, Databases, and more with React.",
href: '/docs/tutorials/react',
cover: '/images/tutorials/react.png',
title: 'React tutorial',
description: 'Learn Appwrite Auth, Databases, and more with React.'
},
{
href: "/docs/tutorials/sveltekit",
cover: "/images/tutorials/svelte.png",
title: "SvelteKit tutorial",
description: "Learn Appwrite Auth, Databases, and more with SvelteKit.",
href: '/docs/tutorials/sveltekit',
cover: '/images/tutorials/svelte.png',
title: 'SvelteKit tutorial',
description: 'Learn Appwrite Auth, Databases, and more with SvelteKit.'
},
{
href: "/docs/tutorials/vue",
cover: "/images/tutorials/vue.png",
title: "Vue tutorial",
description: "Learn Appwrite Auth, Databases, and more with Vue.",
href: '/docs/tutorials/vue',
cover: '/images/tutorials/vue.png',
title: 'Vue tutorial',
description: 'Learn Appwrite Auth, Databases, and more with Vue.'
},
{
href: "/docs/tutorials/android",
cover: "/images/tutorials/android.png",
title: "Android tutorial",
description: "Learn Appwrite Auth, Databases, and more with Android.",
href: '/docs/tutorials/android',
cover: '/images/tutorials/android.png',
title: 'Android tutorial',
description: 'Learn Appwrite Auth, Databases, and more with Android.'
},
{
href: "/docs/tutorials/flutter",
cover: "/images/tutorials/flutter.png",
title: "Flutter tutorial",
description: "Learn Appwrite Auth, Databases, and more with Flutter.",
},
href: '/docs/tutorials/flutter',
cover: '/images/tutorials/flutter.png',
title: 'Flutter tutorial',
description: 'Learn Appwrite Auth, Databases, and more with Flutter.'
}
];
</script>
@@ -66,10 +67,7 @@
<Docs variant="default">
<Sidebar />
<main
class="web-main-section overflow-hidden-break1-to-break3 relative"
id="main"
>
<main class="web-main-section overflow-hidden-break1-to-break3 relative" id="main">
<div class="web-u-opacity-40-mobile bg-blur absolute">
<img src="/images/bgs/docs-blur-1.svg" alt="" />
</div>
@@ -83,15 +81,13 @@
<section class="web-hero is-align-start e-hero-docs relative">
<h1 class="web-display web-u-color-text-primary u-max-width-600">
Learn how to build like a team of hundreds<span
class="web-u-color-text-accent"
Learn how to build like a team of hundreds<span class="web-u-color-text-accent"
>_
</span>
</h1>
<p class="web-description u-max-width-600">
Appwrite helps you build secure and scalable apps, faster. Leverage
Appwrite's powerful APIs to stop fighting technologies and start
delivering value.
Appwrite helps you build secure and scalable apps, faster. Leverage Appwrite's
powerful APIs to stop fighting technologies and start delivering value.
</p>
</section>
<section class="web-hero is-align-start tech-hero">
@@ -99,15 +95,11 @@
Get started with your technologies
</h2>
<p class="web-description u-max-width-600">
Start building with your preferred web, mobile, and native frameworks by
following a quick start guide.
Start building with your preferred web, mobile, and native frameworks by following a
quick start guide.
</p>
<Technologies />
<a
href="/docs/sdks"
class="web-button is-secondary"
style:align-self="start"
>
<a href="/docs/sdks" class="web-button is-secondary" style:align-self="start">
<span class="web-sub-body-500">Explore all technologies</span>
</a>
<div class="web-is-not-mobile spline-wrapper absolute">
@@ -131,9 +123,7 @@
<div class="bg-overlay" />
</section>
<section>
<h2 class="web-title web-u-color-text-primary u-max-width-600">
Show me some code
</h2>
<h2 class="web-title web-u-color-text-primary u-max-width-600">Show me some code</h2>
<p class="web-description u-max-width-600 u-margin-block-start-16">
If you learn best from code examples, follow one of our tutorials.
</p>
@@ -146,12 +136,10 @@
</Carousel>
</section>
<section class="web-hero is-align-start is-no-max-width">
<h2 class="web-title web-u-color-text-primary u-max-width-600">
Explore capabilities
</h2>
<h2 class="web-title web-u-color-text-primary u-max-width-600">Explore capabilities</h2>
<p class="web-description u-max-width-600">
All the core functionalities you need with a scalable and flexible API.
Explore Appwrite's product offerings.
All the core functionalities you need with a scalable and flexible API. Explore
Appwrite's product offerings.
</p>
<div class="u-margin-block-start-24">
<ul class="web-grid-row-4 web-grid-row-4-m-1">
@@ -319,8 +307,8 @@
Explore ways to integrate
</h2>
<p class="web-description u-max-width-600">
Choose how you integrate with Appwrite. Explore references for the
Appwrite SDK, REST API, GraphQL API, or Realtime API.
Choose how you integrate with Appwrite. Explore references for the Appwrite SDK,
REST API, GraphQL API, or Realtime API.
</p>
<div class="u-margin-block-start-24">
<ul class="web-grid-row-2">
@@ -356,8 +344,8 @@
GraphQL
</h4>
<p class="web-sub-body-400 u-margin-block-start-4">
Leverage GraphQL through our SDKs or integrate directly with
REST endpoints.
Leverage GraphQL through our SDKs or integrate directly with REST
endpoints.
</p>
</a>
</li>
@@ -378,19 +366,14 @@
</div>
</section>
<section class="web-hero is-align-start is-no-max-width">
<h2 class="web-title web-u-color-text-primary u-max-width-600">
Migrate to Appwrite
</h2>
<h2 class="web-title web-u-color-text-primary u-max-width-600">Migrate to Appwrite</h2>
<p class="web-description u-max-width-600">
Own your data with automatic data migrations.
</p>
<div class="u-margin-block-start-24">
<ul class="web-grid-row-4">
<li>
<a
href="/docs/advanced/migrations/self-hosted"
class="web-card is-normal"
>
<a href="/docs/advanced/migrations/self-hosted" class="web-card is-normal">
<h4
class="web-sub-body-500 web-u-color-text-primary u-margin-block-start-8"
>
@@ -402,10 +385,7 @@
</a>
</li>
<li>
<a
href="/docs/advanced/migrations/firebase"
class="web-card is-normal"
>
<a href="/docs/advanced/migrations/firebase" class="web-card is-normal">
<h4
class="web-sub-body-500 web-u-color-text-primary u-margin-block-start-8"
>
@@ -417,10 +397,7 @@
</a>
</li>
<li>
<a
href="/docs/advanced/migrations/supabase"
class="web-card is-normal"
>
<a href="/docs/advanced/migrations/supabase" class="web-card is-normal">
<h4
class="web-sub-body-500 web-u-color-text-primary u-margin-block-start-8"
>
@@ -432,10 +409,7 @@
</a>
</li>
<li>
<a
href="/docs/advanced/migrations/nhost"
class="web-card is-normal"
>
<a href="/docs/advanced/migrations/nhost" class="web-card is-normal">
<h4
class="web-sub-body-500 web-u-color-text-primary u-margin-block-start-8"
>
@@ -455,7 +429,7 @@
</Docs>
<style lang="scss">
@use "$scss/abstract/mixins/border-gradient" as gradients;
@use '$scss/abstract/mixins/border-gradient' as gradients;
.e-hero-docs {
@media (min-width: 1280px) {
@@ -507,19 +481,14 @@
.bg-overlay {
position: absolute;
background: linear-gradient(
to right,
#ffffff00 0%,
#ffffff00 400px,
#ffffff
);
background: linear-gradient(to right, #ffffff00 0%, #ffffff00 400px, #ffffff);
top: 0;
right: 10rem;
translate: 100%;
width: 100rem;
height: 100%;
content: "";
content: '';
z-index: 9999;
}
}

View File

@@ -300,6 +300,7 @@ const response = await account.updatePhone(
'+12065550100', // phone
'password' // password
);
```
```client-flutter
Future result = account.updatePhone(
phone: '+12065550100',
@@ -344,6 +345,7 @@ Then, initiate verification for the phone number by calling `account.createPhone
{% multicode %}
```client-web
const response = await account.createPhoneVerification();
```
```client-flutter
Future result = account.createPhoneVerification();
@@ -379,6 +381,7 @@ const response = await account.updatePhoneVerification(
'<USER_ID>', // userId
'<SECRET>' // secret
);
```
```client-flutter
Future result = account.updatePhoneVerification(
userId: '<USER_ID>',
@@ -429,6 +432,7 @@ First, add a TOTP authenticator to the user's account by calling `account.addAut
const { secret, uri } = await account.createMfaAuthenticator(
'totp' // type
);
```
```client-flutter
Future result = account.createMfaAuthenticator(
type: 'totp',

View File

@@ -52,7 +52,7 @@ While still in beta, Appwrite Cloud has limited support for Cloud runtimes. As w
---
* {% icon icon="python" size="l" /%}
* [Python ML](https://hub.docker.com/r/openruntimes/python-ml)
* `python-ML-3.11`
* `python-ml-3.11`
* x86 / arm64
---
* {% icon icon="dart" size="l" /%}
@@ -151,6 +151,11 @@ While still in beta, Appwrite Cloud has limited support for Cloud runtimes. As w
`python-3.12`
* x86 / arm64 / armv7 / armv8
---
* {% icon icon="python" size="l" /%}
* [Python ML](https://hub.docker.com/r/openruntimes/python-ml)
* `python-ml-3.11`
* x86 / arm64
---
* {% icon icon="dart" size="l" /%}
* [Dart](https://hub.docker.com/r/openruntimes/dart/tags)
* `dart-2.16`

View File

@@ -166,7 +166,7 @@
];
const title = 'Quick starts' + DOCS_TITLE_SUFFIX;
const description = '';
const description = 'Get started with your favorite framework and language in just a few clicks.';
const ogImage = DEFAULT_HOST + '/images/open-graph/docs.png';
</script>

View File

@@ -1,10 +1,10 @@
<script lang="ts">
import { MainFooter } from '$lib/components';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { DEFAULT_HOST } from '$lib/utils/metadata';
import { DOCS_TITLE_SUFFIX } from '$routes/titles';
const title = 'Tutorials' + DOCS_TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const description = 'Follow a simple tutorial to get started with Appwrite in your preferred framework quickly and easily.';
const ogImage = DEFAULT_HOST + '/images/open-graph/docs.png';
export let data;

View File

@@ -0,0 +1,645 @@
<script lang="ts">
import { Main } from '$lib/layouts';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { TITLE_SUFFIX } from '$routes/titles';
import FooterNav from '$lib/components/FooterNav.svelte';
import MainFooter from '$lib/components/MainFooter.svelte';
import { type ResultType, Fuse } from '$lib/integrations';
import { writable } from 'svelte/store';
import { autoHash } from '$lib/actions/autoHash';
import type { Integration } from './+page';
import { goto } from '$app/navigation';
import { onDestroy, onMount } from 'svelte';
import { browser } from '$app/environment';
export let data;
const title = 'Integrations' + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
// search functionality
let fuseOptions = {
keys: ['title'],
threshold: 0.3
};
let result: ResultType<Integration> = [];
let hasQuery: boolean;
let query = writable('');
$: query.subscribe((value) => {
hasQuery = value.length > 0;
});
// platform filters
const platforms = ['All', ...data.platforms];
let activePlatform = 'All';
// categories
let activeCategory: string | null = null;
onMount(() => {
if (browser) document.documentElement.setAttribute('data-scroll-smooth', '');
});
onDestroy(() => {
if (browser) document.documentElement.removeAttribute('data-scroll-smooth');
});
</script>
<svelte:head>
<!-- Titles -->
<title>{title}</title>
<meta property="og: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} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
</svelte:head>
<!-- binding for fuse -->
<Fuse list={data.list} options={fuseOptions} bind:query={$query} bind:result />
<Main>
<header class="web-u-sep-block-end u-padding-block-end-0 u-position-relative u-overflow-hidden">
<div class="web-container u-position-relative hero web-u-padding-block-end-0">
<img
src="/images/pages/integration/integration-bg-top-1.png"
alt=""
width="983"
height="985"
class="l-bg-1 u-position-absolute web-is-not-mobile"
/>
<img
src="/images/pages/integration/net-desktop.png"
alt=""
width="895"
height="560"
class="l-bg-2 u-position-absolute web-is-not-mobile"
/>
<img
src="/images/pages/integration/net-desktop.png"
alt=""
width="360"
height="560"
class="l-bg-2 u-position-absolute web-is-only-mobile"
/>
<div class="web-integrations-top-section">
<div
class="l-integrations-hero u-flex-vertical u-main-center u-gap-20 web-u-max-width-680"
>
<div class="web-eyebrow web-u-color-text-primary">
INTEGRATIONS<span class="web-u-color-text-accent">_</span>
</div>
<h1 class="web-headline web-u-color-text-primary">
Discover infinite possibilities
</h1>
<p class="web-description">
Unlock the full potential of Appwrite by seamlessly integrating your
favorite apps with your projects.
</p>
</div>
</div>
<div>
<img src="/images/integrations/rubiks-cube.png" alt="" />
</div>
</div>
</header>
<div class="web-big-padding-section-level-1">
<div>
<div class="web-container">
<div class="l-integrations-grid">
<aside class="u-flex-vertical u-gap-32 sidebar">
<section>
<label class="web-input-button web-u-flex-basis-400">
<span class="web-icon-search" aria-hidden="true"></span>
<input class="text" placeholder="Search" bind:value={$query} />
</label>
</section>
<section class="u-flex-vertical">
<section class="u-flex-vertical u-gap-16">
<h2 class="web-side-nav-header web-eyebrow u-un-break-text">
Platform
</h2>
<ul class="u-flex u-flex-wrap u-gap-8" class:disabled={hasQuery}>
{#each platforms as platform}
<li>
<button
class="tag"
class:is-selected={activePlatform === platform}
class:active-tag={activePlatform === platform}
on:click={() => (activePlatform = platform)}
>{platform}</button
>
</li>
{/each}
</ul>
</section>
<div class="web-u-sep-block-start u-margin-block-24"></div>
<section class="u-flex-vertical u-gap-16">
<h2 class="web-side-nav-header web-eyebrow u-un-break-text">
Categories
</h2>
<div class="u-position-relative is-not-desktop">
<select
class="web-input-text"
bind:value={activeCategory}
on:change={() => {
goto(`#${activeCategory?.toLowerCase()}`);
}}
>
{#each data.categories as category}
{@const integrations = data.integrations.find(
(i) => i.category === category
)}
{#if integrations && (activePlatform === 'All' || integrations.integrations.some( (i) => i.platform.includes(activePlatform) ))}
<option value={category.toLowerCase()}>
{category}
</option>
{/if}
{/each}
<option value={null}> Select category </option>
</select>
<span
class="icon-cheveron-down u-position-absolute u-inset-inline-end-8 u-inset-block-start-8 web-u-pointer-events-none"
aria-hidden="true"
/>
</div>
<ul
class="u-flex-vertical u-gap-16 is-only-desktop"
class:disabled={hasQuery}
>
{#each data.categories as category}
{@const integrations = data.integrations.find(
(i) => i.category === category
)}
{#if integrations && (activePlatform === 'All' || integrations.integrations.some( (i) => i.platform.includes(activePlatform) ))}
<li>
<a
href={`#${category.toLowerCase()}`}
class="web-link"
class:is-pink={category.toLowerCase() ===
activeCategory}
on:click={() =>
activeCategory === category.toLowerCase()}
>{category}</a
>
</li>
{/if}
{/each}
</ul>
</section>
</section>
</aside>
<section>
<div class="u-flex-vertical u-gap-64">
{#if hasQuery}
<section
class="l-max-size-list-cards-section u-flex-vertical u-gap-32"
>
<header class="u-flex-vertical u-gap-4">
<h2 class="web-label web-u-color-text-primary">
Search results
</h2>
<p class="web-description">
{result.length > 0 ? result.length : 'No'} results found
for "{$query}"
</p>
</header>
<div class="l-max-size-list-cards u-flex-vertical u-gap-32">
<ul class="l-grid-1">
{#each result.map((d) => d.item) as item}
<li>
<a
href={item.href}
class="web-card is-normal u-height-100-percent"
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem;"
>
<div class="u-flex u-cross-center u-gap-8">
<img
class="web-user-box-image is-32px"
src={item.product.avatar}
alt={item.product.vendor}
width="32"
height="32"
/>
<h4 class="web-u-color-text-primary">
{item.title}
</h4>
<span
class="icon-arrow-right u-margin-inline-start-auto"
aria-hidden="true"
></span>
</div>
<p
class="web-sub-body-400 u-margin-block-start-4"
>
{item.description}
</p>
</a>
</li>
{/each}
</ul>
</div>
</section>
{:else}
<section class="u-flex-vertical u-gap-32">
<header class="u-flex-vertical u-gap-4">
<h2 class="web-label web-u-color-text-primary">Featured</h2>
<p class="web-description">Top recommended integrations</p>
</header>
<div>
<ul class="web-feature-grid" style="gap: 1rem">
{#each data.featured as item}
<li
class="web-feature-grid-item is-two-columns-desktop-only"
>
<a class="web-overlay-item" href={item.href}>
<img
src={item.cover}
alt={item.title}
class="u-block web-u-media-ratio-16-9 web-u-media-cover"
/>
<div
class="web-user-box u-column-gap-8 u-row-gap-0"
>
<img
class="web-user-box-image"
src={item.product.avatar}
alt={`Avatar for ${item.product.vendor}`}
width="40"
height="40"
style="border-radius: 50%;"
/>
<div
class="web-user-box-name web-main-body-500 u-flex u-gap-8"
>
<span
class="web-u-color-text-primary"
>
{item.title}
</span>
<!-- {#if item.isNew}
<span
class="web-inline-tag is-pink"
>
New
</span>
{/if} -->
</div>
<div
class="web-user-box-username web-caption-400 web-u-color-text-secondary"
>
{item.category}
</div>
</div>
</a>
</li>
{/each}
</ul>
</div>
</section>
{#each data.integrations as { category, description, integrations }}
{#if integrations?.length > 0 && (activePlatform === 'All' || integrations.some( (i) => i.platform.includes(activePlatform) ))}
<section
class="l-max-size-list-cards-section u-flex-vertical u-gap-32"
id={category.toLowerCase()}
use:autoHash={(entries) => {
entries.forEach((entry) => {
if (
entry.isIntersecting &&
activeCategory !== category.toLowerCase()
) {
activeCategory = category.toLowerCase();
}
});
}}
>
<header class="u-flex-vertical u-gap-4">
<h2 class="web-label web-u-color-text-primary">
{category}
</h2>
<p class="web-description">
{description}
</p>
</header>
<div
class="l-max-size-list-cards u-flex-vertical u-gap-32"
>
<ul class="l-grid-1">
{#each integrations as integration, index (`${integration.title}-${index}`)}
{#if activePlatform === 'All' || integration.platform.includes(activePlatform)}
<li>
<a
href={integration.href}
class="web-card is-normal u-height-100-percent"
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem; --card-border-radius: 1.5rem"
>
<div
class="u-flex u-cross-center u-gap-8"
>
<img
class="web-user-box-image is-32px"
src={integration.product
.avatar}
alt={integration.product
.vendor}
width="32"
height="32"
/>
<span
class="icon-arrow-right u-margin-inline-start-auto"
aria-hidden="true"
></span>
</div>
<h4
class="web-u-color-text-primary u-margin-block-start-12"
>
{integration.title}
</h4>
<p
class="web-sub-body-400 u-margin-block-start-4"
>
{integration.description}
</p>
</a>
</li>
{/if}
{/each}
</ul>
<a
href={`#${category.toLowerCase()}`}
class="l-float-button web-button is-text"
>
<span>Show more</span>
</a>
</div>
</section>
{/if}
{/each}
{/if}
</div>
</section>
</div>
</div>
</div>
</div>
<div class="web-big-padding-section-level-1 u-overflow-hidden" style:margin-top="160px">
<div class="web-container">
<div class="web-big-padding-section-level-2 u-position-relative">
<img
src="/images/bgs/pre-footer.png"
alt=""
class="web-pre-footer-bg"
style="z-index:-1"
/>
<div class="u-position-relative">
<section
class="web-hero u-flex u-row-gap-16 u-main-center u-cross-center web-u-max-width-580"
>
<h2
class="web-display u-max-width-600 web-u-text-align-center web-u-color-text-primary"
>
Become a Technology Partner
</h2>
<p class="web-main-body-500">
Join our Technology Partners program to integrate your solutions with
Appwrites API, enhancing functionality and expanding your reach.
</p>
<a
href="/integrations/technology-partner"
class="web-button is-primary web-u-cross-child-center u-margin-block-start-16"
>
<span class="text">Get Started</span>
</a>
</section>
</div>
</div>
<FooterNav />
<MainFooter />
</div>
</div>
</Main>
<style lang="scss">
@use '$scss/abstract' as *;
:global([data-scroll-smooth]) {
scroll-behavior: smooth;
}
.hero {
min-height: pxToRem(620);
@media (min-width: 768px) {
display: grid;
grid-template-columns: 60% minmax(0, 1fr);
gap: pxToRem(32);
justify-content: space-between;
align-items: center;
position: relative;
> :nth-child(5) {
transform-origin: left center;
scale: 1.25;
position: relative;
left: pxToRem(-30);
}
}
@media (max-width: 768px) {
> :nth-child(5) {
transform-origin: left center;
scale: 2;
left: 0;
}
}
@media (max-width: 767.9px) {
display: block;
overflow: hidden;
gap: 2rem;
> :first-child {
max-width: 40rem;
margin-inline: auto;
}
> :nth-child(5) {
scale: 1;
width: 100%;
height: 24rem;
position: relative;
img {
position: absolute;
display: block;
width: 40rem;
left: 50%;
top: 50%;
transform: translate(-30%, -40%);
max-block-size: unset;
max-inline-size: unset;
}
}
}
}
.web-pre-footer-bg {
position: absolute;
top: clamp(300px, 50vw, 50%);
left: clamp(300px, 50vw, 50%);
transform: translate(-58%, -72%);
width: clamp(1200px, 200vw, 3000px);
height: auto;
max-inline-size: unset;
max-block-size: unset;
}
.l-float-button {
display: none;
}
/* more tha 9 items */
.l-max-size-list-cards-section {
scroll-snap-align: start;
scroll-margin-top: pxToRem(120);
}
.l-max-size-list-cards {
&:where(:has(> ul > li:nth-child(10))) {
position: relative;
&::before {
position: absolute;
bottom: 0;
height: 100%;
width: 100%;
max-height: pxToRem(350);
content: '';
display: block;
background: linear-gradient(
180deg,
rgba(25, 25, 28, 0) 0%,
rgba(25, 25, 28, 0.92) 90%,
#19191c 100%
);
transition: var(--transition);
}
.l-float-button {
position: absolute;
inset-inline: 0;
inset-block-end: pxToRem(20);
margin-inline: auto;
display: flex;
}
}
}
:where(:target) {
.l-max-size-list-cards {
overflow: visible;
max-block-size: none;
scroll-margin: 100px;
&::before {
opacity: 0;
pointer-events: none;
}
.l-float-button {
display: none;
}
}
}
.l-grid-1 {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
gap: 1rem;
@media #{$break1} {
gap: 1.25rem;
}
}
.l-integrations-grid {
position: relative;
@media #{$break1} {
gap: 0;
padding-block-start: pxToRem(80);
}
.disabled {
& > li {
pointer-events: none;
opacity: 0.4;
}
}
.sidebar {
margin-bottom: pxToRem(60);
@media #{$break2open} {
position: sticky;
top: 50px;
height: 500px;
}
.tag {
min-width: pxToRem(42);
&.active-tag {
background-color: #fff;
color: #000;
}
}
}
@media #{$break2open} {
display: grid;
gap: pxToRem(68);
grid-template-columns: pxToRem(240) 1fr;
padding-block-start: pxToRem(40);
}
}
.l-integrations-hero {
@media #{$break1} {
}
@media #{$break2open} {
}
}
.l-bg-1 {
max-inline-size: none;
max-block-size: none;
inset-block-end: -600px;
inset-inline-start: -600px;
opacity: 0.5;
}
.l-bg-2 {
inset-block-start: 0;
inset-inline-start: 0;
opacity: 0.5;
}
.web-feature-grid {
@media #{$break1} {
gap: 1rem;
}
}
.web-feature-grid {
@media #{$break1} {
gap: 1rem;
}
}
</style>

View File

@@ -0,0 +1,81 @@
import { base } from '$app/paths';
import { groupBy } from 'remeda';
export type Integration = {
title: string;
description: string;
featured?: boolean;
cover: string;
isNew?: boolean;
isPartner?: boolean;
platform: string[];
category: string;
product: {
avatar: string;
vendor: string;
description: string;
};
href: string;
images: string[];
};
const categoryDescriptions = Object.entries({
ai: 'Machine learning and AI capabilities',
auth: 'User authentication and authorization',
databases: 'Manage database systems',
logging: 'Monitor and analyze application logs',
messaging: 'Real-time communication platforms',
payments: 'Secure online payment processing',
search: 'Implement search functionalities',
storage: 'Storage for data and media',
deployments: 'Seamlessly deploy your code',
});
export const load = () => {
const integrationsGlob = import.meta.glob('./**/*.markdoc', {
eager: true
});
const categories: string[] = [];
const platforms: string[] = [];
const integrations = Object.entries(integrationsGlob).map(([filepath, integrationList]) => {
const { frontmatter } = integrationList as {
frontmatter: Integration;
};
const slug = filepath.replace('./', '').replace('/+page.markdoc', '');
const integrationName = slug.slice(slug.lastIndexOf('/') + 1);
frontmatter.platform.map((platform) => platforms.push(platform));
categories.push(frontmatter.category);
return {
...frontmatter,
href: `${base}/integrations/${integrationName}`
};
});
const groupedIntegrations = groupBy(integrations, (i) => i.category);
const integrationsWithDescriptions = Object.entries(groupedIntegrations).map(
([category, integrations]) => {
const description = categoryDescriptions.find(
([key]) => key.toLowerCase() === category.toLowerCase()
)?.[1];
return {
category,
description,
integrations
};
}
);
return {
integrations: integrationsWithDescriptions,
list: integrations,
categories: new Set(categories),
platforms: new Set(platforms),
featured: integrations.filter((i) => i.featured)
};
};

View File

@@ -0,0 +1,75 @@
---
layout: integration
title: Image classification with Hugging Face
description: Understand and label the contents of images
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/ai-hugging-face-image-classification/cover.png
category: AI
product:
avatar: '/images/integrations/avatars/hugging-face.png'
vendor: Hugging Face
description: 'Hugging Face is a leading AI company that offers an extensive library of pre-trained models for various natural language processing and computer vision tasks, including image classification.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/ai-hugging-face-image-classification/cover.png
- /images/integrations/ai-hugging-face-image-classification/appwrite-functions-image-classification-hugging-face.png
- /images/integrations/ai-hugging-face-image-classification/appwrite-functions-image-classification-hugging-face.png
- /images/integrations/ai-hugging-face-image-classification/appwrite-functions-env-variables-image-classification-hugging-face.png
---
Image classification is a key application of machine learning that involves categorizing images into predefined classes. Hugging Face is a leading AI company that offers an extensive library of pre-trained models for various natural language processing and computer vision tasks, including image classification. By integrating Hugging Face's powerful models with your applications, you can leverage state-of-the-art technology to automate and enhance image analysis.
# How does the integration work?
You can utilize a pre-built Appwrite function template to add image classification with Hugging Face to your app. This will allow you to upload an image to an Appwrite storage bucket and store labels from the image in an Appwrite collection.
# How to implement
To implement the Hugging Face image classification function, there are several steps you must complete:
## Step 1: Sign up for Hugging Face
First, you must [sign up for a Hugging Face account](https://huggingface.co/join). Once your account is set up, visit your profile settings, head to the [Access Tokens](https://huggingface.co/settings/tokens) page, and create an **access token** with the **Inference** permissions. Save this token for further usage.
![Create API token](/images/integrations/ai-hugging-face-image-classification/hugging-face-create-api-token.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click on the **Templates** tab, and search for the **Image Classification** function template.
![Function template](/images/integrations/ai-hugging-face-image-classification/appwrite-functions-image-classification-hugging-face.png)
During the setup process, click on the checkbox to generate an Appwrite API key on completion and add the **Hugging Face access token** in the **Variables** step. If you are self-hosting Appwrite, then click on the **optional variables** dropdown and update the Appwrite endpoint to your instances publicly accessible endpoint.
![Environment variables](/images/integrations/ai-hugging-face-image-classification/appwrite-functions-env-variables-image-classification-hugging-face.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
## Step 3: Test the function
Once all the steps are complete, it is time to test the function! Use the Appwrite console or one of Appwrites SDKs to [upload an image](https://appwrite.io/docs/references/cloud/client-web/storage#createFile) to the `image_classification` storage bucket. If successful, you will find a response saved in the `image_classification` collection in the `ai` database in the following format:
| image | labels |
| --- | --- |
| `66a13bf100318c752f1b` | `[{"label":"llama","score":0.9664694666862488},{"label":"comic book","score":0.019199883565306664},{"label":"suit, suit of clothes","score":0.005637330934405327},{"label":"television, television system","score":0.00037627643905580044},{"label":"muzzle","score":0.00019786457414738834}]` |
The `image` attribute contains the ID of the image file uploaded to the `image_classification` storage bucket, and the `labels` attribute contains the response from Hugging Face, including all the labels and their confidence score.
# Read more about Hugging Face and Appwrite Functions
If you would like to learn more about Hugging Face and Appwrite Functions, we have some resources that you should visit:
- [Sign up for Hugging Face](https://huggingface.co/login)
- [Set up the Hugging Face provider in Appwrite](https://appwrite.io/docs/products/ai/tutorials/image-classification)
- [Building with Appwrite AI Function templates](https://appwrite.io/blog/post/building-with-ai-function-templates)
- [Introducing the Python machine learning runtime](https://appwrite.io/blog/post/introducing-python-machine-learning-runtime)
- [Find more function templates](https://appwrite.io/docs/products/functions/templates)
- [Appwrite Functions API reference](https://appwrite.io/docs/references)

View File

@@ -0,0 +1,77 @@
---
layout: integration
title: Language translation with Hugging Face
description: Translate text between languages
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/ai-hugging-face-language-translation/cover.png
category: AI
product:
avatar: '/images/integrations/avatars/hugging-face.png'
vendor: Hugging Face
description: 'Hugging Face is a leading AI company that offers an extensive library of pre-trained models for various natural language processing and computer vision tasks, including image classification.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/ai-hugging-face-language-translation/cover.png
- /images/integrations/ai-hugging-face-language-translation/hugging-face-create-api-token.png
- /images/integrations/ai-hugging-face-language-translation/language-translation-function-template.png
- /images/integrations/ai-hugging-face-language-translation/language-translation-env-variables.png
- /images/integrations/ai-hugging-face-language-translation/language-translation-demo.png
---
Language translation is a fundamental task in natural language processing that involves converting text from one language to another. Hugging Face offers a robust library of pre-trained models for various natural language processing tasks, including language translation. By integrating Hugging Face's advanced models with your applications, you can automate and enhance translating text across different languages.
# How does the integration work?
You can utilize a pre-built Appwrite function template to add language translation with Hugging Face to your app. This will allow you to translate text from one language to another.
# How to implement
To implement the Hugging Face language translation function, there are several steps you must complete:
## Step 1: Sign up for Hugging Face
First, you must [sign up for a Hugging Face account](https://huggingface.co/join). Once your account is set up, visit your profile settings, head to the [Access Tokens](https://huggingface.co/settings/tokens) page, and create an **access token** with **Inference** permissions. Save this token for further usage.
![Create API token](/images/integrations/ai-hugging-face-language-translation/hugging-face-create-api-token.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Language Translation** function template.
![Function template](/images/integrations/ai-hugging-face-language-translation/language-translation-function-template.png)
During the setup process, add the **Hugging Face access token** in the **Variables** step.
![Environment variables](/images/integrations/ai-hugging-face-language-translation/language-translation-env-variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
## Step 3: Test the function
Once the function is ready, visit the **Domains** tab on the **Functions** page and copy the domain URL to test the function. You can open this URL in your browser to test with our pre-built interface.
![Demo](/images/integrations/ai-hugging-face-language-translation/language-translation-demo.png)
You can also use tools like Postman, cURL, or your favorite programming language to send a POST (HTTP) request with a prompt and receive a response from the function.
```bash
curl -X POST http://DEPLOYED_FUNCTION_DOMAIN \
-H "Content-Type: application/json" \
-d '{"source": "What is Appwrite?"}'
```
# Read more about Hugging Face and Appwrite Functions
If you would like to learn more about Hugging Face and Appwrite Functions, we have some resources that you should visit:
- [Sign up for Hugging Face](https://huggingface.co/login)
- [Set up the Hugging Face provider in Appwrite](https://appwrite.io/docs/products/ai/tutorials/language-translation)
- [Find more function templates](https://appwrite.io/docs/products/functions/templates)
- [Appwrite Functions API reference](https://appwrite.io/docs/references)

View File

@@ -0,0 +1,73 @@
---
layout: integration
title: Speech recognition with Hugging Face
description: Process speech audio into text
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/ai-hugging-face-speech-recognition/cover.png
category: AI
product:
avatar: '/images/integrations/avatars/hugging-face.png'
vendor: Hugging Face
description: 'Hugging Face is a leading AI company that offers an extensive library of pre-trained models for various natural language processing and computer vision tasks, including image classification.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/ai-hugging-face-speech-recognition/cover.png
- /images/integrations/ai-hugging-face-speech-recognition/token.png
- /images/integrations/ai-hugging-face-speech-recognition/template.png
- /images/integrations/ai-hugging-face-speech-recognition/variables.png
---
Speech recognition is a transformative technology that converts spoken language into text. Hugging Face, a prominent AI company offers a comprehensive library of pre-trained models for various natural language processing tasks, including speech recognition. By integrating Hugging Face's models with your applications, you can automate and enhance the transcription and analysis of audio content.
# How does the integration work?
You can utilize a pre-built Appwrite function template to add speech recognition with Hugging Face to your app. This will allow you to upload an audio file to an Appwrite storage bucket and store the recognized speech in an Appwrite collection as text.
# How to implement
To implement the Hugging Face speech recognition function, there are several steps you must complete:
## Step 1: Sign up for Hugging Face
First, you must [sign up for a Hugging Face account](https://huggingface.co/join). Once your account is set up, visit your profile settings, head to the [Access Tokens](https://huggingface.co/settings/tokens) page, and create an **access token** with the **Inference** permissions. Save this token for further usage.
![Create API token](/images/integrations/ai-hugging-face-speech-recognition/token.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Speech Recognition** function template.
![Function template](/images/integrations/ai-hugging-face-speech-recognition/template.png)
During the setup process, click the checkbox to generate an Appwrite API key on completion and add the **Hugging Face access token** in the **Variables** step. If you are self-hosting Appwrite, click the **optional variables** dropdown and update the Appwrite endpoint to your instances publicly accessible endpoint.
![Env variables](/images/integrations/ai-hugging-face-speech-recognition/variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
## Step 3: Test the Function
Once all the steps are complete, it is time to test the function! Use the Appwrite console or one of Appwrites SDKs to [upload an audio file](https://appwrite.io/docs/references/cloud/client-web/storage#createFile) to the `speech_recognition` storage bucket. If successful, you will find a response saved in the `speech_recognition` collection in the `ai` database in the following format:
| audio | speech |
| --- | --- |
| 66a7b386000a1042305c | my thought i have nobody by a beauty and will as you've poured mr rochester is sub and that so don't find simpus and devoted about to at might in a |
The `audio` attribute contains the ID of the audio file uploaded to the `speech_recognition` storage bucket, and the `speech` attribute contains the response from Hugging Face.
# Read more about Hugging Face and Appwrite Functions
If you would like to learn more about Hugging Face and Appwrite Functions, we have some resources that you should visit:
- [Sign up for Hugging Face](https://huggingface.co/login)
- [Set up the Hugging Face provider in Appwrite](https://appwrite.io/docs/products/ai/tutorials/object-detection)
- [Find more function templates](https://appwrite.io/docs/products/functions/templates)
- [Appwrite Functions API reference](https://appwrite.io/docs/references)

View File

@@ -0,0 +1,77 @@
---
layout: integration
title: Prompt ChatGPT
description: Send text prompts to OpenAI GPT-3.5 and receive text generations
date: 2024-07-30
featured: true
isPartner: true
isNew: true
cover: /images/integrations/ai-openai/cover.png
category: AI
product:
avatar: '/images/integrations/avatars/openai.png'
vendor: OpenAI
description: 'The OpenAI API allows you to integrate advanced AI models into your app.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/ai-openai/cover.png
- /images/integrations/ai-openai/api-key.png
- /images/integrations/ai-openai/template.png
- /images/integrations/ai-openai/variables.png
- /images/integrations/ai-openai/demo.png
---
The OpenAI API allows you to integrate advanced AI models into your app. With the API, you can access powerful language models like GPT-3.5, GPT-4, and GPT-4o, which can perform a variety of tasks, including text generation, translation, summarization, and even coding assistance.
The API is designed to be user-friendly, providing endpoints that can be easily accessed through HTTP requests. OpenAI also provides detailed documentation and examples to help users get started and make the most of the API.
# How does the integration work?
Appwrite integrates OpenAIs API to provide you with access to powerful text generation out-of-the-box with prospects to implement other features such as image creation and language translations.
# How to implement
To implement the OpenAI, there are several steps you must complete:
## Step 1: Create an Open AI account
First, [create an account on the OpenAI platform](https://platform.openai.com/) and set up your default project. Visit the [**API keys**](https://platform.openai.com/api-keys) page to create your secret key. Save this key for later usage.
![API key](/images/integrations/ai-openai/api-key.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In case you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click on the **Templates** tab, and search for the **ChatGPT** function template.
![Function template](/images/integrations/ai-openai/template.png)
Add the **OpenAI API key** you saved in the **Variables** step. Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
![Env variables](/images/integrations/ai-openai/variables.png)
## Step 3: Test the function
Once the function is ready, visit the **Domains** tab on the **Functions** page and copy the domain URL to test the function. You can open this URL in your browser to test with our pre-built interface.
![Demo](/images/integrations/ai-openai/demo.png)
You can also use tools like Postman, cURL, or your favorite programming language to send a POST (HTTP) request with a prompt and receive a response from the Perplexity API.
```bash
curl -X POST http://DEPLOYED_FUNCTION_DOMAIN \
-H "Content-Type: application/json" \
-d '{"prompt": "What is Appwrite?"}'
```
# Read more about OpenAI and Appwrite Functions
If you would like to learn more about Open AI, visit these resources:
- [Create an OpenAI developer account](https://platform.openai.com/docs/quickstart)
- [Build an intelligent chatbot with ChatGPT and Appwrite Functions](https://appwrite.io/blog/post/function-template-prompt-chatgpt)
- [Integrating OpenAI - Appwrite Docs](https://appwrite.io/docs/products/ai/integrations/openai)
- [Appwrite Functions docs](https://appwrite.io/docs/products/functions)

View File

@@ -0,0 +1,74 @@
---
layout: integration
title: Prompt Perplexity
description: Send text prompts to Perplexity and receive text generations
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/ai-perplexity/cover.png
category: AI
product:
avatar: '/images/integrations/avatars/perplexity.png'
vendor: Perplexity
description: 'Perplexity is an advanced AI tool that generates high-quality text based on given prompts.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/ai-perplexity/cover.png
- /images/integrations/ai-perplexity/api-key.png
- /images/integrations/ai-perplexity/template.png
- /images/integrations/ai-perplexity/variables.png
- /images/integrations/ai-perplexity/demo.png
---
Perplexity is an advanced AI tool that generates high-quality text based on given prompts. It's designed to improve applications by providing sophisticated text analysis and generation capabilities.
# How does the integration work?
You can utilize a pre-built Appwrite function template to create a chatbot using Perplexity. This will allow you to send text prompts to the Perplexity API and receive generated text responses, enriching your app's functionality.
# How to implement
To implement the Perplexity integration, follow these simple steps:
## Step 1: Create a Perplexity account
First, [create an account on Perplexity](https://perplexity.ai), head to the [API Settings](https://www.perplexity.ai/settings/api), configure your credit card for payments, and generate an API key. Save this API key for further usage.
![API key](/images/integrations/ai-perplexity/api-key.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In case you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click on the **Templates** tab, and search for the **Perplexity** function template.
![Function template](/images/integrations/ai-perplexity/template.png)
Add the **Perplexity API key** you saved in the **Variables** step. Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
![Env variables](/images/integrations/ai-perplexity/variables.png)
## Step 3: Test the function
Once the function is ready, visit the **Domains** tab on the **Functions** page and copy the domain URL to test the function. You can open this URL in your browser to test with our pre-built interface.
![Demo](/images/integrations/ai-perplexity/demo.png)
You can also use tools like Postman, cURL, or your favorite programming language to send a POST (HTTP) request with a prompt and receive a response from the Perplexity API.
```bash
curl -X POST http://DEPLOYED_FUNCTION_DOMAIN \
-H "Content-Type: application/json" \
-d '{"prompt": "What is Appwrite?"}'
```
# Read more about Perplexity and Appwrite Functions
If you would like to learn more about Perplexity and Appwrite Functions, we have some resources that you should visit:
- [Integrating Perplexity - Appwrite Docs](https://appwrite.io/docs/products/ai/integrations/perplexity)
- [More on Appwrite AI integrations](https://appwrite.io/blog/post/announcing-appwrite-new-ai-integrations)
- [Appwrite Functions docs](https://appwrite.io/docs/products/functions)

View File

@@ -0,0 +1,128 @@
---
layout: integration
title: Deployments with GitHub
description: Manage versions and deploy Appwrite Functions
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/deployments-github/cover.png
category: Deployments
product:
avatar: '/images/integrations/avatars/github.png'
vendor: GitHub
description: 'GitHub is a web-based platform that facilitates version control and collaborative software development using Git.'
platform:
- 'Self-hosted'
images:
- /images/integrations/deployments-github/cover.png
- /images/integrations/deployments-github/create.png
- /images/integrations/deployments-github/installed.png
---
GitHub is a web-based platform that facilitates version control and collaborative software development using Git. It enables developers to host, review code, manage projects, and work together on software development. GitHub offers tools for issue tracking, project management, and documentation, enhancing team collaboration. It hosts millions of open-source projects from developers across the world.
# How does the integration work?
Appwrite supports a Git integration to enable the generation of repositories for function templates and manage automatic deployments for any Appwrite Functions through GitHub.
> Note: For the 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/).
>
# How to implement
To implement the GitHub integration for Appwrite Functions, there are several steps you must complete:
## Step 1: Create a GitHub App
Visit the [Developer Settings on GitHub](https://github.com/settings/apps) to create a new GitHub app.
![Create new GitHub app](/images/integrations/deployments-github/create.png)
Add a GitHub name (keep in mind that this will be publicly displayed), a relevant description, and a homepage URL for your application. Then, add the following URLs:
| Type of URL | URL |
| --- | --- |
| Callback URL | `https://[HOSTNAME_OR_IP]/v1/vcs/github/callback` |
| Callback URL | `https://[HOSTNAME_OR_IP]/v1/account/sessions/oauth2/callback/github/console` |
| Webhook URL | `https://[HOSTNAME_OR_IP]/v1/vcs/github/events` |
Under the **Callback URLs** section, check the **Request user authentication (OAuth)** during **installation** box. After that, request the following permissions:
{% tabs %}
{% tabsitem #repository title="Repository permissions" %}
| Permission | Access |
| --- | --- |
| Administration | Read and write |
| Checks | Read and write |
| Commit Statuses | Read and write |
| Contents | Read and write |
| Issues | Read and write |
| Metadata | Read-only |
| Pull Requests | Read and write |
| Webhooks | Read and write |
{% /tabsitem %}
{% tabsitem #account title="Account permissions" %}
| Permission | Access |
| --- | --- |
| Email address | Read-only |
{% /tabsitem %}
{% /tabs %}
Under the **Subscribe to events** section, check the **Pull request** and **Push** boxes. Lastly, allow **Any account** to install the GitHub app.
Once the app is created, create a new **client secret** and **private key**, and configure a **webhook secret**.
## Step 2: Add GitHub provider to the Appwrite instance
For this step, you must [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already.
Visit the `.env` file created for your Appwrite instance and update the following environment variables:
| Variable | Description |
| --- | --- |
| _APP_DOMAIN | Your main Appwrite domain used to access the Appwrite Console. When setting a public suffix domain, Appwrite will attempt to issue a valid SSL certificate automatically. When used with a dev domain, Appwrite will assign a self-signed SSL certificate. If you're using a proxy for localhost development, such as [ngrok](https://ngrok.com/), this will be the domain of your localhost proxy. |
| _APP_DOMAIN_TARGET | A hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite _APP_DOMAIN variable. If you're using a proxy for localhost development, such as [ngrok](https://ngrok.com/), this will be the domain of your localhost proxy, such as `dd65-2405-201-4013-d8d7-b4c5-fb73-39f9-285c.ngrok.io`. |
| _APP_DOMAIN_FUNCTIONS | This will be used for system-generated [function domains](https://appwrite.io/docs/products/functions/domains). When a function domain is generated, it will be `[UNIQUE_ID].[_APP_DOMAIN_FUNCTIONS]`. If `_APP_DOMAIN_FUNCTIONS` is set to example.com for example, the generated domain for functions will be something like `64d4d22db370ae41a32e.example.com`. You can use the same value as used for the Appwrite `_APP_DOMAIN` variable. |
| _APP_VCS_GITHUB_APP_NAME | Name of your GitHub app. This is visible as the slug in your GitHub app's public link. For example, if the public link of your GitHub app is https://github.com/apps/test-appwrite-integration, then the app name will be test-appwrite-integration. |
| _APP_VCS_GITHUB_PRIVATE_KEY | RSA private key from GitHub wrapped with double quotes and newlines replaced with `\n`. |
| _APP_VCS_GITHUB_APP_ID | GitHub application ID from your GitHub app. |
| _APP_VCS_GITHUB_CLIENT_ID | GitHub client ID from your GitHub app. |
| _APP_VCS_GITHUB_CLIENT_SECRET | GitHub client secret from your GitHub app. |
| _APP_VCS_GITHUB_WEBHOOK_SECRET | GitHub webhook secret from your GitHub app. |
This is how the fields would look like in the `.env` file:
```bash
_APP_DOMAIN=appwrite.example.com
_APP_DOMAIN_TARGET=appwrite.example.com
_APP_DOMAIN_FUNCTIONS=functions.example.com
_APP_VCS_GITHUB_APP_NAME=my-github-app
_APP_VCS_GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAuT8f3lo/X83hfvb0ZN/KD2pl86o/jl3ywKrkj/PQZBmtEv/z\nIugE//sfFoHWc4cizkcji+n3FNU+GEdvMioKuJlPBqPTY8hAbVn7R0geZLpDV/rs\n[...]\n-----END RSA PRIVATE KEY-----"
_APP_VCS_GITHUB_APP_ID=12415
_APP_VCS_GITHUB_CLIENT_ID=Iv1.35asdf43asd
_APP_VCS_GITHUB_CLIENT_SECRET=35rsdse532q13
_APP_VCS_GITHUB_WEBHOOK_SECRET=super-secret
```
After that, run the following Docker Compose commands in your terminal to restart your Appwrite containers and verify if the changes have been successfully applied:
```bash
docker compose up -d --force-recreate
docker compose exec appwrite vars
```
## Step 3: Test the provider
To test the provider, go to the **Settings** page in your Appwrite project, navigate to the **Git configuration** section, and add an installation. On successful installation, you should be able to find your app installation in the same section.
![Installed GitHub app](/images/integrations/deployments-github/installed.png)
# Read more about GitHub and Appwrite Functions
If you would like to learn more about GitHub, we have some resources that you should visit:
- [Create a GitHub app](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps)
- [GitHub setup docs for Appwrite Functions (self-hosted)](https://appwrite.io/docs/advanced/self-hosting/functions)
- [Appwrite Functions API reference](https://appwrite.io/docs/references/cloud/server-nodejs/functions)

View File

@@ -0,0 +1,74 @@
---
layout: integration
title: Email with SendGrid
description: Send customized emails to your users
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/email-sendgrid/cover.png
category: Messaging
product:
avatar: '/images/integrations/avatars/sendgrid.png'
vendor: SendGrid
description: 'SendGrid is a cloud-based service that provides email delivery and marketing solutions.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/email-sendgrid/cover.png
- /images/integrations/email-sendgrid/welcome-guide.png
- /images/integrations/email-sendgrid/provider.png
- /images/integrations/email-sendgrid/email.png
---
SendGrid is a cloud-based service that provides email delivery and marketing solutions. It helps businesses manage email communications, including transactional emails (like password resets and order confirmations) and marketing emails (newsletters and promotions).
# How does the integration work?
You can use the SendGrid provider in Appwrite Messaging to send customized emails to your users for various purposes such as reminders, promotions, announcements, and even custom authentication flows. They can be sent immediately or scheduled for later.
# How to implement
To implement the SendGrid provider in Appwrite Messaging, there are several steps you must complete:
## Step 1: Sign up on Sendgrid
First, you must [sign up for a SendGrid account](https://signup.sendgrid.com/) and finish your account setup.
![SendGrid welcome guide](/images/integrations/email-sendgrid/welcome-guide.png)
Next, [create an API key](https://www.twilio.com/docs/sendgrid/ui/account-and-settings/api-keys) with full access and save the key for further usage. After, follow SendGrid's [Domain Authentication](https://www.twilio.com/docs/sendgrid/ui/account-and-settings/how-to-set-up-domain-authentication) process to authenticate your domain name. If you dont own a domain, you can follow their [Single Sender Verification](https://www.twilio.com/docs/sendgrid/ui/sending-email/sender-verification) process to verify your Sender identity.
## Step 2: Add SendGrid provider to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Messaging** page, click on the **Providers** tab, and **create a new Email provider**.
![Setup email provider](/images/integrations/email-sendgrid/provider.png)
Fill in the following fields:
| Field name | |
| --- | --- |
| API key | The full access API key you saved from the SendGrid dashboard. |
| Sender email | The provider sends emails from this sender email. The sender email must either be an email under an authenticated domain or a verified sender identity. |
| Sender name | The sender name that appears in the emails sent from this provider. |
| Reply-to email | The reply-to email that appears in the emails sent from this provider. The reply-to email must either be an email under an authenticated domain or a verified sender identity. |
| Reply-to name | The reply-to name that appears in the emails sent from this provider. |
## Step 3: Test the SendGrid provider
Before you proceed, you must already have at least one [topic](https://appwrite.io/docs/products/messaging/topics) or [target](https://appwrite.io/docs/products/messaging/targets) set up.
Once the provider is set up, you can go to the **Messages** tab on the **Messaging** page and **create an email message**. You can add the test message, configure the users to send the message to, and pick when the message should be sent out.
![Create email](/images/integrations/email-sendgrid/email.png)
# Read more about Sendgrid and Appwrite Messaging
If you would like to learn more about Sendgrid and Appwrite Messaging, we have some resources that you should visit:
- [Sign up for SendGrid](https://signup.sendgrid.com/)
- [Set up the SendGrid provider in Appwrite Messaging](https://appwrite.io/docs/products/messaging/sendgrid)
- [Send email messages through Appwrite Messaging](https://appwrite.io/docs/products/messaging/send-email-messages)
- [Appwrite Messaging API reference](https://appwrite.io/docs/references/cloud/server-nodejs/messaging)

View File

@@ -0,0 +1,93 @@
---
layout: integration
title: Payments with Lemon Squeezy
description: Receive payments and store paid orders
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/lemon-squeezy-payments/cover.png
category: Payments
product:
avatar: '/images/integrations/avatars/lemon-squeezy.png'
vendor: Lemon Squeezy
description: 'Lemon Squeezy is a platform designed to simplify the process of selling digital products online.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/lemon-squeezy-payments/cover.png
- /images/integrations/lemon-squeezy-payments/dashboard.png
- /images/integrations/lemon-squeezy-payments/template.png
- /images/integrations/lemon-squeezy-payments/variables.png
- /images/integrations/lemon-squeezy-payments/web-platform.png
- /images/integrations/lemon-squeezy-payments/demo.png
- /images/integrations/lemon-squeezy-payments/database.png
---
Lemon Squeezy is a platform designed to simplify the process of selling digital products online. Their product focuses on providing an all-in-one solution for creators to manage sales, subscriptions, and digital delivery. It includes features such as easy product creation, automated tax handling, customizable checkout pages, and robust analytics. This comprehensive tool is tailored for digital entrepreneurs, allowing them to focus on creating content while Lemon Squeezy handles the technical aspects of online sales.
# How does the integration work?
You can utilize a pre-built Appwrite function template to enable payments via Lemon Squeezy in your app. You can then use this to sell software, send PDF books, give access to video courses, or any other digital services your business needs.
# How to implement
To implement the Lemon Squeezy payments integration, there are several steps you must complete:
## Step 1: Setup Lemon Squeezy
First, [sign up on Lemon Squeezy](https://www.lemonsqueezy.com/) and add a new store.
![Lemon Squeezy dashboard](/images/integrations/lemon-squeezy-payments/dashboard.png)
From your Lemon Squeezy dashboard, save the following details for further usage:
| Field name | |
| --- | --- |
| Variant ID | Head to **Store** > **Products** from the left sidebar. Create a new product with the pricing type as **Single payment** and add all other mandatory details such as name, price, and tax category. Click on the product dropdown menu (…) to get the variant ID. |
| Store ID | Head to **Settings** > **Stores** from the left sidebar. The store ID will be a number visible next to your stores URL. |
| API key | Head to **Settings** > **API** from the left sidebar. Create a new API key. |
| Webhook secret | Head to **Settings** > **Webhooks** from the left sidebar. Add a temporary endpoint `https://temporary-endpoint` (we will replace this with our final endpoint later), create a new webhook secret, and select the event `order_created`. |
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Payments with Lemon Squeezy** function template.
![Function template](/images/integrations/lemon-squeezy-payments/template.png)
During the setup process, click the checkbox to generate an Appwrite API key on completion and add the **Lemon Squeezy API key**, **webhook secret**, **store ID**, and **variant ID** in the **Variables** step. If you are self-hosting Appwrite, click on the **optional variables** dropdown and update the Appwrite endpoint to your instances publicly accessible endpoint.
![Env variables](/images/integrations/lemon-squeezy-payments/variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic. Once the function is deployed, go to the **Domains** tab on the **Function** page, copy the domain, and update it in your **Webhooks settings** in the following format:
```bash
https://DEPLOYED_FUNCTION_DOMAIN/webhook
```
Additionally, edit the product you created and add your function URL as the **Button link** under the **Confirmation modal** section.
## Step 3: Test the function
Once all the steps are complete, it is time to test the function! First, copy the function URL, go to the **Appwrite project dashboard**, and add it to the **Platforms** section as a web app. This will register your function URL as an authorized hostname to interact with Appwrite (to prevent CORS).
![Add web platform](/images/integrations/lemon-squeezy-payments/web-platform.png)
Then, open it in your browser to test the function and access the pre-built interactive UI. You can anonymously log in through this UI and create a payment order using [Lemon Squeezy's test card number](https://docs.lemonsqueezy.com/help/getting-started/test-mode#test-card-numbers). As soon as this process is completed, the function UI will show you the complete order.
![Demo](/images/integrations/lemon-squeezy-payments/demo.png)
You can visit the **Databases** page in your Appwrite project, enter the `orders` database and the `orders` collection within that, and find your orders.
![Paid orders in database](/images/integrations/lemon-squeezy-payments/database.png)
# Read more about Lemon Squeezy Payments and Appwrite Functions
If you would like to learn more about Lemon Squeezy Payments and Appwrite Functions, we have some resources that you should visit:
- [Sign up for Lemon Squeezy](https://lemonsqueezy.com)
- [Add a new product to your Lemon Squeezy store](https://docs.lemonsqueezy.com/help/products/adding-products)
- [Learn more about Functions templates in Appwrite docs](https://appwrite.io/docs/products/functions/templates)

View File

@@ -0,0 +1,93 @@
---
layout: integration
title: Subscriptions with Lemon Squeezy
description: Receive recurring payments and grant subscribers extra permissions
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/lemon-squeezy-subscriptions/cover.png
category: Payments
product:
avatar: '/images/integrations/avatars/lemon-squeezy.png'
vendor: Lemon Squeezy
description: 'Lemon Squeezy is a platform designed to simplify the process of selling digital products online.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/lemon-squeezy-subscriptions/cover.png
- /images/integrations/lemon-squeezy-subscriptions/dashboard.png
- /images/integrations/lemon-squeezy-subscriptions/template.png
- /images/integrations/lemon-squeezy-subscriptions/variables.png
- /images/integrations/lemon-squeezy-subscriptions/web-platform.png
- /images/integrations/lemon-squeezy-subscriptions/demo.png
- /images/integrations/lemon-squeezy-subscriptions/user.png
---
Lemon Squeezy is a platform designed to simplify the process of selling digital products online. Their product focuses on providing an all-in-one solution for creators to manage sales, subscriptions, and digital delivery. It includes features such as easy product creation, automated tax handling, customizable checkout pages, and robust analytics. This comprehensive tool is tailored for digital entrepreneurs, allowing them to focus on creating content while Lemon Squeezy handles the technical aspects of online sales.
# How does the integration work?
You can utilize a pre-built Appwrite function template to enable subscriptions via Lemon Squeezy in your app. This will allow you to accept recurring payments from your customers and grant them extra permissions.
# How to implement
To implement the Lemon Squeezy subscriptions integration, there are several steps you must complete:
## Step 1: Setup Lemon Squeezy
First, [sign up on Lemon Squeezy](https://www.lemonsqueezy.com/) and add a new store.
![Lemon Squeezy dashboard](/images/integrations/lemon-squeezy-subscriptions/dashboard.png)
From your Lemon Squeezy dashboard, save the following details for further usage:
| Field name | |
| --- | --- |
| Variant ID | Head to **Store** > **Products** from the left sidebar. Create a new product with the pricing type as **Subscription** and add all other mandatory details such as name, price, payment schedule, and tax category. Click on the product dropdown menu (…) to get the variant ID. |
| Store ID | Head to **Settings** > **Stores** from the left sidebar. The store ID will be a number visible next to your stores URL. |
| API key | Head to **Settings** > **API** from the left sidebar. Create a new API key. |
| Webhook secret | Head to **Settings** > **Webhooks** from the left sidebar. Add a temporary endpoint `https://temporary-endpoint` (we will replace this with our final endpoint later), create a new webhook secret, and select the events `subscription_created` and `subscription_expired`. |
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Subscriptions with Lemon Squeezy** function template.
![Function template](/images/integrations/lemon-squeezy-subscriptions/template.png)
During the setup process, click the checkbox to generate an Appwrite API key on completion and add the **Lemon Squeezy API key**, **webhook secret**, **store ID**, and **variant ID** in the **Variables** step. If you are self-hosting Appwrite, click on the **optional variables** dropdown and update the Appwrite endpoint to your instances publicly accessible endpoint.
![Env variables](/images/integrations/lemon-squeezy-subscriptions/variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic. Once the function is deployed, go to the **Domains** tab on the **Function** page, copy the domain, and update it in your **Webhooks settings** in the following format:
```bash
https://DEPLOYED_FUNCTION_DOMAIN/webhook
```
Additionally, edit the product you created and add your function URL as the **Button link** under the **Confirmation modal** section.
## Step 3: Test the function
Once all the steps are complete, it is time to test the function! First, copy the function URL, go to the **Appwrite project dashboard**, and add it to the **Platforms** section as a web app. This will register your function URL as an authorized hostname to interact with Appwrite (to prevent CORS).
![Add web platform](/images/integrations/lemon-squeezy-subscriptions/web-platform.png)
Then, open it in your browser to test the function and access the pre-built interactive UI. You can anonymously log in through this UI and create a subscription using [Lemon Squeezy's test card number](https://docs.lemonsqueezy.com/help/getting-started/test-mode#test-card-numbers). As soon as this process is complete, the function UI will show that you are subscribed.
![Demo](/images/integrations/lemon-squeezy-subscriptions/demo.png)
Additionally, your user on Appwrite will feature the `subscriber` label, which you can verify by visiting the **Auth** page in your Appwrite project and clicking on the user.
![Subscribed user](/images/integrations/lemon-squeezy-subscriptions/user.png)
# Read more about Lemon Squeezy Subscriptions and Appwrite Functions
If you would like to learn more about Lemon Squeezy Subscriptions and Appwrite Functions, we have some resources that you should visit:
- [Sign up for Lemon Squeezy](https://lemonsqueezy.com)
- [Add a new product to your Lemon Squeezy store](https://docs.lemonsqueezy.com/help/products/adding-products)
- [Learn more about Functions templates in Appwrite docs](https://appwrite.io/docs/products/functions/templates)

View File

@@ -0,0 +1,79 @@
---
layout: integration
title: Logging with AppSignal
description: Store logs and track issues on your Appwrite instance
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/logging-appsignal/cover.png
category: Logging
product:
avatar: '/images/integrations/avatars/appsignal.png'
vendor: AppSignal
description: 'AppSignal is a comprehensive monitoring and error-tracking tool designed for developers to gain insights into the performance of their applications.'
platform:
- 'Self-hosted'
images:
- /images/integrations/logging-appsignal/cover.png
- /images/integrations/logging-appsignal/api-key.png
- /images/integrations/logging-appsignal/errors-list.png
- /images/integrations/logging-appsignal/error.png
---
AppSignal is a comprehensive monitoring and error-tracking tool designed for developers to gain insights into the performance of their applications. It provides detailed metrics on application performance, error tracking, and server health, enabling developers to diagnose and resolve issues efficiently. AppSignal supports various programming languages and frameworks, offering seamless integration and an intuitive interface. It helps teams monitor application health in real time, receive alerts on critical issues, and analyze performance data to optimize their code and infrastructure, ultimately ensuring a smooth user experience and maintaining high application reliability.
# How does the integration work?
If you are using self-hosting Appwrite, you can use the AppSignal provider for error-tracking and logging for your Appwrite instance.
# How to implement
To implement the AppSignal provider for logging, there are several steps you must complete:
## Step 1: Sign up for AppSignal
First, [sign up on AppSignal](https://appsignal.com/users/sign_up) and create your first organization (or join an existing one). Head to the **App settings** from the left sidebar and click on **Push & deploy**. Copy the **app-specific Push API key** for further usage.
![API key](/images/integrations/logging-appsignal/api-key.png)
## Step 2: Add AppSignal provider to your Appwrite instance
For this step, you must [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already.
Visit the `.env` file created for your Appwrite instance and update the following environment variables:
```bash
_APP_LOGGING_PROVIDER=appSignal
_APP_LOGGING_CONFIG=APPSIGNAL_API_KEY
```
After that, run the following Docker Compose commands in your terminal to restart your Appwrite containers and verify if the changes have been successfully applied:
```bash
docker compose up -d --force-recreate
docker compose exec appwrite vars
```
## Step 3: Test the provider
Once the AppSignal provider is configured, run the following command in your terminal:
```bash
docker compose exec appwrite ssl --domain=”wrongdomain.com
```
Doing so will show errors in your AppSignal **Errors** page.
![Errors list](/images/integrations/logging-appsignal/errors-list.png)
You can also view the error summary for further details.
![Error](/images/integrations/logging-appsignal/error.png)
# Read more about AppSignal and Appwrite
If you would like to learn more about AppSignal and Appwrite, we have some resources that you should visit:
- [Sign up for AppSignal](https://appsignal.com/users/sign_up)
- [Handling errors in Appwrite self-hosted instances](https://appwrite.io/docs/advanced/self-hosting/production#errors)

View File

@@ -0,0 +1,79 @@
---
layout: integration
title: Logging with Raygun
description: Store logs and track issues on your Appwrite instance
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/logging-raygun/cover.png
category: Logging
product:
avatar: '/images/integrations/avatars/raygun.png'
vendor: Raygun
description: 'Raygun is an application performance monitoring (APM) and error tracking tool designed for software developers to identify and resolve issues in their applications quickly. It provides real-time insights into software performance, error diagnostics, and user experience, helping teams to detect, diagnose, and fix errors faster. With features like crash reporting, real user monitoring, and deployment tracking, Raygun helps ensure the stability and efficiency of applications.'
platform:
- 'Self-hosted'
images:
- /images/integrations/logging-raygun/cover.png
- /images/integrations/logging-raygun/api-key.png
- /images/integrations/logging-raygun/crash-reporting.png
- /images/integrations/logging-raygun/error.png
---
Raygun is an application performance monitoring (APM) and error tracking tool designed for software developers to identify and resolve issues in their applications quickly. It provides real-time insights into software performance, error diagnostics, and user experience, helping teams to detect, diagnose, and fix errors faster. With features like crash reporting, real user monitoring, and deployment tracking, Raygun helps ensure the stability and efficiency of applications, making it an essential tool for maintaining high-quality software and delivering a seamless user experience.
# How does the integration work?
If you are using self-hosting Appwrite, you can use the Raygun provider for error-tracking and logging for your Appwrite instance.
# How to implement
To implement the Raygun provider for logging, there are several steps you must complete:
## Step 1: Sign up for Raygun
First, [sign up on Raygun](https://app.raygun.com/signup?product=cr) (pick **Crash Reporting** as the product youre most interested in) and create your first application. Head to **Application settings** from the left-side navbar and copy your **API Key**.
![API key](/images/integrations/logging-raygun/api-key.png)
## Step 2: Add Raygun provider to your Appwrite instance
For this step, you must [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already.
Visit the `.env` file created for your Appwrite instance and update the following environment variables:
```bash
_APP_LOGGING_PROVIDER=raygun
_APP_LOGGING_CONFIG=RAYGUN_API_KEY
```
After that, run the following Docker Compose commands in your terminal to restart your Appwrite containers and verify if the changes have been successfully applied:
```bash
docker compose up -d --force-recreate
docker compose exec appwrite vars
```
## Step 3: Test the provider
Once the Sentry provider is configured, run the following command in your terminal:
```bash
docker compose exec appwrite ssl --domain=”wrongdomain.com
```
Doing so will show errors in your Raygun Crash Reporting dashboard.
![Raygun Crash Reporting](/images/integrations/logging-raygun/crash-reporting.png)
You can also view the error summary for further details.
![Error](/images/integrations/logging-raygun/error.png)
# Read more about Raygun and Appwrite
If you would like to learn more about Raygun and Appwrite, we have some resources that you should visit:
- [Sign up for Raygun](https://app.raygun.com/signup?product=cr)
- [Handling errors in Appwrite self-hosted instances](https://appwrite.io/docs/advanced/self-hosting/production#errors)

View File

@@ -0,0 +1,83 @@
---
layout: integration
title: Logging with Sentry
description: Store logs and track issues on your Appwrite instance
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/logging-sentry/cover.png
category: Logging
product:
avatar: '/images/integrations/avatars/sentry.png'
vendor: Sentry
description: 'Sentry is an open-source error-tracking and performance-monitoring tool designed to help developers identify, diagnose, and fix issues in real-time.'
platform:
- 'Self-hosted'
images:
- /images/integrations/logging-sentry/cover.png
- /images/integrations/logging-sentry/project.png
- /images/integrations/logging-sentry/issues.png
- /images/integrations/logging-sentry/issue-details.png
---
Sentry is an open-source error-tracking and performance-monitoring tool designed to help developers identify, diagnose, and fix issues in real-time. It provides comprehensive insights into application health by capturing and analyzing error events, performance metrics, and user feedback. Sentry supports multiple programming languages and frameworks, making it versatile for various development environments. With features like stack traces, context data, and alerting, Sentry allows teams to quickly pinpoint the root cause of issues and improve the overall quality and reliability of their software applications.
# How does the integration work?
If you are using self-hosting Appwrite, you can use the Sentry provider for error-tracking and logging for your Appwrite instance.
# How to implement
To implement the Sentry provider for logging, there are several steps you must complete:
## Step 1: Set up Sentry
First, [sign up on Sentry](https://sentry.io/signup/) and create a new project.
![Create project](/images/integrations/logging-sentry/project.png)
Head to **Settings** > **Projects** > Select your Sentry project > **Client Keys (DSN)**. Save the DSN for further usage.
## Step 2: Add Sentry provider to your Appwrite instance
For this step, you must [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already.
To add the Sentry provider, you need to slightly reconfigure your DSN. Your Sentry DSN is made up of 3 parts: **public key**, **URI**, and **project ID**. The Appwrite logging configuration expects a string in the format `SENTRY_PUBLIC_KEY;SENTRY_PROJECT_ID`. For example, if your Sentry DSN is `https://public@sentry.example.com/1`, then the Appwrite logging configuration will be `public;1`.
Visit the `.env` file created for your Appwrite instance and update the following environment variables:
```bash
_APP_LOGGING_PROVIDER=sentry
_APP_LOGGING_CONFIG=SENTRY_PUBLIC_KEY;SENTRY_PROJECT_ID
```
After that, run the following Docker Compose commands in your terminal to restart your Appwrite containers and verify if the changes have been successfully applied:
```bash
docker compose up -d --force-recreate
docker compose exec appwrite vars
```
## Step 3: Test the provider
Once the Sentry provider is configured, run the following command in your terminal:
```bash
docker compose exec appwrite ssl --domain=”wrongdomain.com
```
Doing so will show errors in your Sentry **Issues** page.
![Issues](/images/integrations/logging-sentry/issues.png)
You can also view the error details for more information.
![Issue details](/images/integrations/logging-sentry/issue-details.png)
# Read more about Sentry and Appwrite
If you would like to learn more about Sentry and Appwrite, we have some resources that you should visit:
- [Sign up for Sentry](https://sentry.io/signup/)
- [Handling errors in Appwrite self-hosted instances](https://appwrite.io/docs/advanced/self-hosting/production#errors)

View File

@@ -0,0 +1,64 @@
---
layout: integration
title: OAuth with Amazon
description: Authenticate users with an existing Amazon account
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/oauth-amazon/cover.png
category: Auth
product:
avatar: '/images/integrations/avatars/amazon.png'
vendor: Amazon
description: 'Amazon is a global e-commerce platform that offers a wide selection of products, from electronics, books, and apparel to household goods, groceries, and digital media.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/oauth-amazon/cover.png
- /images/integrations/oauth-amazon/security-profile.png
- /images/integrations/oauth-amazon/provider.png
- /images/integrations/oauth-amazon/allowed-return-urls.png
---
Amazon is a global e-commerce platform that offers a wide selection of products, from electronics, books, and apparel to household goods, groceries, and digital media. Amazon offers an OAuth provider to simplify the process of integrating Amazon services into various applications, enhancing the authentication user experience while maintaining robust security standards.
# How does the integration work?
You can use the Amazon OAuth adapter in Appwrite Auth for user authentication and management. This can be convenient for users because they can start using your app without creating a new account. It can also be more secure, because the user has one less password that could become vulnerable.
# How to implement
To implement the Amazon OAuth adapter in Appwrite Auth, there are several steps you must complete:
## Step 1: Create an Amazon Developer account
First, [sign up for an Amazon Developer account](https://www.amazon.com/ap/register?clientContext=130-6830764-7565500&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&siteState=clientContext%3D140-5240481-9393408%2CsourceUrl%3Dhttps%253A%252F%252Fdeveloper.amazon.com%252Fsettings%252Fconsole%252Fregistration%253Freturn_to%253D%252Fapps-and-games%2Csignature%3DR6AIXlj2Bj2Fwc7EBuqfl0CNCjUbh6Ej3D&marketPlaceId=ATVPDKIKX0DER&language=en_US&pageId=amzn_developer_portal&openid.return_to=https%3A%2F%2Fdeveloper.amazon.com%2Fsettings%2Fconsole%2Fregistration%3Freturn_to%3D%252Fapps-and-games&prevRID=93HMKYWW3JS4T3Q5EJ37&openid.assoc_handle=mas_dev_portal&openid.mode=checkid_setup&prepopulatedLoginId=&failedSignInCount=0&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0), head to the [Login With Amazon console](https://developer.amazon.com/loginwithamazon/console/site/lwa/overview.html), and create a new security profile with details of your app.
![New security profile](/images/integrations/oauth-amazon/security-profile.png)
Save the generated **Client ID** and **Client Secret** for later usage.
## Step 2: Add Amazon OAuth adapter to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Auth** page, open the **Settings** tab, and click on Amazon under the **OAuth2 Providers** section.
![Amazon provider](/images/integrations/oauth-amazon/provider.png)
Add the **Client ID** and **Client secret** you saved from the security profile you created. Copy the URI to add to the **Allowed Return URLs** field in the **Web Settings** of the security profile in the Amazon Developer console.
![New security profile](/images/integrations/oauth-amazon/security-profile.png)
## Step 3: Test the provider.
Follow the [OAuth 2 login](https://appwrite.io/docs/products/auth/oauth2#init) flow to test your provider.
# Read more about Amazon and Appwrite Auth
If you would like to learn more about Amazon and Appwrite Auth, we have some resources that you should visit:
- [Sign up for an Amazon Developer account](https://www.amazon.com/ap/register?clientContext=130-6830764-7565500&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&siteState=clientContext%3D140-5240481-9393408%2CsourceUrl%3Dhttps%253A%252F%252Fdeveloper.amazon.com%252Fsettings%252Fconsole%252Fregistration%253Freturn_to%253D%252Fapps-and-games%2Csignature%3DR6AIXlj2Bj2Fwc7EBuqfl0CNCjUbh6Ej3D&marketPlaceId=ATVPDKIKX0DER&language=en_US&pageId=amzn_developer_portal&openid.return_to=https%3A%2F%2Fdeveloper.amazon.com%2Fsettings%2Fconsole%2Fregistration%3Freturn_to%3D%252Fapps-and-games&prevRID=93HMKYWW3JS4T3Q5EJ37&openid.assoc_handle=mas_dev_portal&openid.mode=checkid_setup&prepopulatedLoginId=&failedSignInCount=0&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0)
- [Implement OAuth login in your apps using Appwrite Auth](https://appwrite.io/docs/products/auth/oauth2)
- [Understanding OAuth and OpenID Connect](https://appwrite.io/blog/post/oauth-openid)
- [Appwrite Auth API reference](https://appwrite.io/docs/references/cloud/client-web/account)

View File

@@ -0,0 +1,74 @@
---
layout: integration
title: OAuth with Apple
description: Authenticate users with an existing Apple account
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/oauth-apple/cover.png
category: Auth
product:
avatar: '/images/integrations/avatars/apple.png'
vendor: Apple
description: 'An Apple ID is a unique account that allows access to Apple services, including the App Store, iCloud, iTunes, Apple Music, and more.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/oauth-apple/cover.png
- /images/integrations/oauth-apple/apple-developer-program.png
- /images/integrations/oauth-apple/provider.png
---
An Apple ID is a unique account that allows access to Apple services, including the App Store, iCloud, iTunes, Apple Music, and more. It serves as a key to the Apple ecosystem, allowing users to synchronize their data across Apple devices, download apps, purchase music, and access various features like FaceTime and iMessage. The Apple ID consists of an email address and a password, with options for added security through two-factor authentication. It is essential for managing personal information, subscriptions, and settings across all Apple products.
# How does the integration work?
You can use the Apple OAuth adapter in Appwrite Auth for user authentication and management. This can be convenient for users because they can start using your app without creating a new account. It can also be more secure, because the user has one less password that could become vulnerable.
# How to implement
To implement the Apple OAuth adapter in Appwrite Auth, there are several steps you must complete:
## Step 1: Create an Apple Developer account
First, [sign up for the Apple Developer program](https://developer.apple.com/programs).
![Apple Developer Program](/images/integrations/oauth-apple/apple-developer-program.png)
Before you configure any other details, you must create an **App ID** for our app. To do that, go to XCode and open the `ios` folder in your source code. Navigate to the **Signing & Capabilities** tab, click the **Capability** button, search for `Sign in with Apple`, and double-click the result to add it. Then, modify the **Bundle Identifier** to a unique string by prefixing it with any letters of your choice and change the **Team** to your Apple Developer team. This will automatically create an **App ID** for your app.
After that, you will also need to create a **Services ID**. Visit your Apple Developer account, head to **Program resources** > **Certificates, Identifiers & Profiles** > **Identifiers**, and register a new **Service ID**, setting your Bundle ID as the unique identifier.
View the service ID, enable **Sign in with Apple**, and in its configuration, select your primary App ID, input `appwrite.io` (or the domain of your self-hosted instance) under **Domains and Subdomains,** and temporarily add the URL `https://temporary-endpoint.com/` under **Return URLs**. This temporary URI will be replaced with the final URI once the OAuth2 adapter is configured on Appwrite.
Head to your Apple Developer account and save the following details:
| Field name | |
| --- | --- |
| Services ID Identifier | Head to Apple Developer account > Program resources > Certificates, Identifiers & Profiles > Identifiers and view the Services ID. |
| Team ID | Head to Apple Developer account > Membership details > Team ID |
| Authentication key (.p8 file) | Head to Apple Developer account > Program resources > Certificates, Identifiers & Profiles > Keys. Create a key and give it a name. Enable Sign in with Apple and register your key. Download the key, open it in a text editor, and copy the content. |
| Authentication key ID | Head to Apple Developer account > Program resources > Certificates, Identifiers & Profiles > Keys. Click on your key to view details. |
## Step 2: Add Apple OAuth adapter to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Auth** page, open the **Settings** tab, and click on Apple under the **OAuth2 Providers** section.
![Apple provider](/images/integrations/oauth-apple/provider.png)
Add the **Services ID Identifier** (in the Bundle ID field), **Key ID**, **Team ID**, and **P8 File** content that you saved from your Apple Developer account. Copy the URI and add it to the **Return URLs** in the configuration of the Services ID you created in your Apple Developer account.
## Step 3: Test the provider.
Follow the [OAuth 2 login](https://appwrite.io/docs/products/auth/oauth2#init) flow to test your provider.
# Read more about Google and Appwrite Auth
If you would like to learn more about Google and Appwrite Auth, we have some resources that you should visit:
- [Sign up for the Apple Developer program](https://developer.apple.com/programs)
- [Implement OAuth login in your apps using Appwrite Auth](https://appwrite.io/docs/products/auth/oauth2)
- [Understanding OAuth and OpenID Connect](https://appwrite.io/blog/post/oauth-openid)
- [Appwrite Auth API reference](https://appwrite.io/docs/references/cloud/client-web/account)

View File

@@ -0,0 +1,64 @@
---
layout: integration
title: OAuth with Discord
description: Authenticate users with an existing Discord account
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/oauth-discord/cover.png
category: Auth
product:
avatar: '/images/integrations/avatars/discord.png'
vendor: Discord
description: 'Discord is a popular communication platform designed for creating communities.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/oauth-discord/cover.png
- /images/integrations/oauth-discord/new-app.png
- /images/integrations/oauth-discord/oauth2.png
- /images/integrations/oauth-discord/provider.png
---
Discord is a popular communication platform designed for creating communities. It supports text, voice, and video communication, making it ideal for both casual conversations and organized group activities. Initially popular among gamers, Discord has expanded to various communities, including education, business, and hobbyist groups.
# How does the integration work?
You can use the Discord OAuth adapter in Appwrite Auth for user authentication and management. This can be convenient for users because they can start using your app without creating a new account. It can also be more secure, because the user has one less password that could become vulnerable.
# How to implement
To implement the Discord OAuth adapter in Appwrite Auth, there are several steps you must complete:
## Step 1: Register a Discord Developer application
First, head to the Discord Developer portal and [register an application](https://discord.com/developers/applications).
![New Discord app](/images/integrations/oauth-discord/new-app.png)
Head to the **OAuth2** tab under **Settings** and save the **client ID** and **client secret**. Once we create the adapter on Appwrite, we will return to add a redirect URI.
## Step 2: Add Discord OAuth adapter to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Auth** page, open the **Settings** tab, and click on **Discord** under the **OAuth2 Providers** section.
![OAuth2 settings](/images/integrations/oauth-discord/oauth2.png)
Add the **client ID** and **client secret** you saved from your Discord app and copy the URI to add to the **Redirect** field in the **OAuth2** settings in your Discord app.
![Discord provider](/images/integrations/oauth-discord/provider.png)
## Step 3: Test the provider.
Follow the [OAuth 2 login](https://appwrite.io/docs/products/auth/oauth2#init) flow to test your provider.
# Read more about Discord and Appwrite Auth
If you would like to learn more about Discord and Appwrite Auth, we have some resources that you should visit:
- [Register a Discord Developer application](https://discord.com/developers/applications)
- [Implement OAuth login in your apps using Appwrite Auth](https://appwrite.io/docs/products/auth/oauth2)
- [Understanding OAuth and OpenID Connect](https://appwrite.io/blog/post/oauth-openid)
- [Appwrite Auth API reference](https://appwrite.io/docs/references/cloud/client-web/account)

View File

@@ -0,0 +1,69 @@
---
layout: integration
title: OAuth with Google
description: Authenticate users with an existing Google account
date: 2024-07-30
featured: true
isPartner: true
isNew: true
cover: /images/integrations/oauth-google/cover.png
category: Auth
product:
avatar: '/images/integrations/avatars/google.png'
vendor: Google
description: 'Google Workspace is a comprehensive suite of cloud-based productivity and collaboration tools developed by Google.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/oauth-google/cover.png
- /images/integrations/oauth-google/consent-screen.png
- /images/integrations/oauth-google/client-id.png
- /images/integrations/oauth-google/provider.png
- /images/integrations/oauth-google/redirect-uri.png
---
Google Workspace, formerly known as G Suite, is a comprehensive suite of cloud-based productivity and collaboration tools developed by Google. It includes popular applications such as Gmail for email, Google Drive for cloud storage, Google Docs for document creation, Google Sheets for spreadsheets, and Google Slides for presentations. Additionally, it offers tools for communication and collaboration, including Google Meet for video conferencing and Google Chat for instant messaging. Google Workspace is designed for businesses, educational institutions, and individuals, providing seamless integration, real-time collaboration, and robust security features to enhance productivity and streamline workflows.
# How does the integration work?
You can use the Google OAuth adapter in Appwrite Auth for user authentication and management. This approach is convenient for users, allowing them to start using your app without creating a new account. Additionally, it enhances security by eliminating the need for users to manage yet another password, reducing the risk of potential vulnerabilities.
# How to implement
To implement the Google OAuth adapter in Appwrite Auth, there are several steps you must complete:
## Step 1: Create an OAuth 2.0 client ID on Google Cloud
First, [log into the Google Cloud Console](https://console.cloud.google.com/), create a new project, click on **APIs and Services** in the left-side navbar, and open the **OAuth consent screen** page. Add all the required details about your app and select the scopes `.../auth/userinfo.email`, `.../auth/userinfo.profile`, and `openid`.
![OAuth consent screen](/images/integrations/oauth-google/consent-screen.png)
Next, go to the **Credentials** page under **APIs and Services** in the left-side navbar and create a new **OAuth 2.0 client ID**. Select the **application type** as `Web application,` and in the **authorized redirect URIs** field, temporarily add the URL `https://temporary-endpoint.com/`. This temporary URI will be replaced with the final URI once the OAuth2 adapter is configured on Appwrite.
![OAuth client ID](/images/integrations/oauth-google/client-id.png)
Save the generated **Client ID** and **Client secret** for later usage.
## Step 2: Add Google OAuth adapter to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Auth** page, open the **Settings** tab, and click on Google under the **OAuth2 Providers** section.
![Google provider](/images/integrations/oauth-google/provider.png)
Add the **Client ID** and **Client secret** you saved from Google Cloud and copy the URI to add to the **authorized redirect URIs** field in the credential you created on Google Cloud.
![OAuth redirect URI](/images/integrations/oauth-google/redirect-uri.png)
## Step 3: Test the provider.
Follow the [OAuth 2 login](https://appwrite.io/docs/products/auth/oauth2#init) flow to test your provider.
# Read more about Google and Appwrite Auth
If you would like to learn more about Google and Appwrite Auth, we have some resources that you should visit:
- [How to set up Google authentication in React with Appwrite](https://appwrite.io/blog/post/set-up-google-auth-appwrite-react)
- [Implement OAuth login in your apps using Appwrite Auth](https://appwrite.io/docs/products/auth/oauth2)
- [Understanding OAuth and OpenID Connect](https://appwrite.io/blog/post/oauth-openid)
- [Appwrite Auth API reference](https://appwrite.io/docs/references/cloud/client-web/account)

View File

@@ -0,0 +1,64 @@
---
layout: integration
title: OAuth with Notion
description: Authenticate users with an existing Notion account
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/oauth-notion/cover.png
category: Auth
product:
avatar: '/images/integrations/avatars/notion.png'
vendor: Notion
description: 'Notion is a versatile productivity tool that combines note-taking, task management, and collaboration features into a single application.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/oauth-notion/cover.png
- /images/integrations/oauth-notion/new-integration.png
- /images/integrations/oauth-notion/provider.png
- /images/integrations/oauth-notion/redirect-uri.png
---
Notion is a versatile productivity tool that combines note-taking, task management, and collaboration features into a single application. It allows users to create customizable workspaces where they can organize their projects, documents, and databases. Notion's flexibility comes from its block-based system, which lets users add various types of content, such as text, images, lists, tables, and more, in a modular fashion. This makes it suitable for personal use, team collaboration, and project management.
# How does the integration work?
You can use the Notion OAuth adapter in Appwrite Auth for user authentication and management. This can be convenient for users because they can start using your app without creating a new account. It can also be more secure, because the user has one less password that could become vulnerable.
# How to implement
To implement the Notion OAuth adapter in Appwrite Auth, there are several steps you must complete:
## Step 1: Create a Notion integration
First, head over to Notion and [create a new integration](https://www.notion.so/profile/integrations). Set the integration type as **Public** if you want your integration to be used by any Notion user, not just members of your workspace (otherwise, set it as **Internal**), and add all the mandatory info. In the **Redirect URIs** field, temporarily add the URL `https://temporary-endpoint/`. This temporary URI will be replaced with the final URI once the OAuth2 adapter is configured on Appwrite.
![New Notion integration](/images/integrations/oauth-notion/new-integration.png)
From the **Configuration** tab, save the **OAuth Client ID** and **OAuth Client Secret** for later usage.
## Step 2: Add Notion OAuth adapter to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Auth** page, open the **Settings** tab, and click on **Notion** under the **OAuth2 Providers** section.
![Notion provider](/images/integrations/oauth-notion/provider.png)
Add the **OAuth Client ID** and **OAuth Client Secret** you saved from your Notion integration and copy the URI to add to the **Redirect URIs** field on the **Basic Information** tab in your Notion integration.
![Redirect URI](/images/integrations/oauth-notion/redirect-uri.png)
## Step 3: Test the provider.
Follow the [OAuth 2 login](https://appwrite.io/docs/products/auth/oauth2#init) flow to test your provider.
# Read more about Notion and Appwrite Auth
If you would like to learn more about Notion and Appwrite Auth, we have some resources that you should visit:
- [Create a Notion integration](https://www.notion.so/profile/integrations)
- [Implement OAuth login in your apps using Appwrite Auth](https://appwrite.io/docs/products/auth/oauth2)
- [Understanding OAuth and OpenID Connect](https://appwrite.io/blog/post/oauth-openid)
- [Appwrite Auth API reference](https://appwrite.io/docs/references/cloud/client-web/account)

View File

@@ -0,0 +1,80 @@
---
layout: integration
title: Phone auth with Twilio
description: Authenticate users through OTPs in SMSes via Twilio
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/phone-auth-twilio/cover.png
category: Auth
product:
avatar: '/images/integrations/avatars/twilio.png'
vendor: Twilio
description: 'Twilio is a cloud communications platform that provides programmable communication tools using web APIs and SDKs.'
platform:
- 'Self-hosted'
images:
- /images/integrations/phone-auth-twilio/cover.png
- /images/integrations/phone-auth-twilio/twilio-console.png
- /images/integrations/phone-auth-twilio/user.png
---
Twilio is a cloud communications platform that provides programmable communication tools for making and receiving phone calls, sending and receiving text messages, and performing other communication functions using web APIs and SDKs.
# How does the integration work?
If you are using self-hosting Appwrite, you can use the Twilio provider to deliver OTPs (one-time passwords) for phone authentication in Appwrite Auth. This is a great passwordless alternative to standard authentication methods, especially for mobile apps, and has several benefits, such as enhanced security, higher user convenience, reduced password fatigue, and easier fraud prevention.
Phone authentication via OTPs is also available on [Appwrite Cloud](https://cloud.appwrite.io) without the need to manually integrate a provider.
# How to implement
To implement the Twilio provider for phone authentication, there are several steps you must complete:
## Step 1: Sign up for Twilio
First, you must [sign up for a Twilio account](https://www.twilio.com/try-twilio), upgrade your account (in case you want to message numbers other than your own), and purchase a phone number with the SMS capability.
![Twilio console](/images/integrations/phone-auth-twilio/twilio-console.png)
Ensure you save the following information for later use:
| Field name | |
| --- | --- |
| Account SID | Head to **Twilio console** > **Account info** > **Account SID**. |
| Auth token | Head to **Twilio console** > **Account info** > **Auth Token**. |
| Phone number | You can access numbers by navigating to your **Twilio console** > **Develop** > **Phone Numbers** > **Manage** > **Active Numbers**. |
## Step 2: Add Twilio provider to your Appwrite instance
For this step, you must [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already.
Visit the `.env` file created for your Appwrite instance and update the following environment variables:
```bash
_APP_SMS_PROVIDER=sms://[ACCOUNT_SID]:[AUTH_TOKEN]@twilio
_APP_SMS_FROM=[TWILIO_PHONE_NUMBER]
```
After that, run the following Docker Compose commands in your terminal to restart your Appwrite containers and verify if the changes have been successfully applied:
```bash
docker compose up -d --force-recreate
docker compose exec appwrite vars
```
## Step 3: Test the provider
To test the provider, you must [implement the phone (SMS) authentication flow](https://appwrite.io/docs/products/auth/phone-sms) in a web or mobile app. On successful login, you should see a user on the **Auth** page of your Appwrite project with their phone number visible as the identifier.
![User](/images/integrations/phone-auth-twilio/user.png)
# Read more about Twilio and Appwrite Auth
If you would like to learn more about phone authentication with Twilio and Appwrite Auth, we have some resources that you should visit:
- [Sign up for Twilio](https://www.twilio.com/try-twilio)
- [SMS delivery docs for Appwrite (self-hosted)](https://appwrite.io/docs/advanced/self-hosting/sms)
- [Appwrite phone auth docs](https://appwrite.io/docs/products/auth/phone-sms)
- [Appwrite Accounts API reference](https://appwrite.io/docs/references/cloud/client-web/account)

View File

@@ -0,0 +1,70 @@
---
layout: integration
title: Push notifications with APNs
description: Send customized notifications to your users
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/push-apns/cover.png
category: Messaging
product:
avatar: '/images/integrations/avatars/apple.png'
vendor: Apple
description: 'Apple Push Notification Service is an Apple platform that enables developers to send notifications to iOS devices, macOS computers, and other Apple devices.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/push-apns/cover.png
- /images/integrations/push-apns/apple-developer-program.png
- /images/integrations/push-apns/provider.png
---
Apple Push Notification Service (APNs) is an Apple platform that enables developers to send notifications to iOS devices, macOS computers, and other Apple devices. It allows app developers to send remote notifications, alerting users to new content, messages, updates, and app-specific information.
# How does the integration work?
You can use the APNs provider in Appwrite Messaging to send push notifications to your users Apple devices. APNs is a best-effort service and will attempt to deliver messages to your device when it's online and available again. APNs will save the last message for 30 days or less and attempt delivery as soon as it's online.
# How to implement
To implement the APNs provider in Appwrite Messaging, there are several steps you must complete:
## Step 1: Sign up on Apple Developer
First, [sign up for the Apple Developer program](https://developer.apple.com/programs).
![Apple developer program](/images/integrations/push-apns/apple-developer-program.png)
Before you configure any other details, you must create an **App ID** for our app. To do that, go to XCode and open the `ios` folder in your source code. Navigate to the **Signing & Capabilities** tab, click the **+ Capability** button, search for `Push Notifications`, and double-click the result to add it. Then, modify the **Bundle Identifier** to a unique string by prefixing it with any letters of your choice and then change the **Team** to your Apple Developer team. This will automatically create an **App ID** for your app.
Head to the Apple Developer account and save the following details:
| Field name | |
| --- | --- |
| Bundle ID | Head to **Apple Developer account** > **Program resources** > **Certificates, Identifiers & Profiles** > **Identifiers** |
| Team ID | Head to **Apple Developer account** > **Membership details** > **Team ID** |
| Authentication key (.p8 file) | Head to **Apple Developer account** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. Create a key and give it a name. Enable the **Apple Push Notifications service (APNs)**, and register your key. |
| Authentication key ID | Head to **Apple Developer account** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. Click on your key to view details. |
## Step 2: Add APNs provider to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Messaging** page, click on the **Providers** tab, and **create a new push notifications provider**.
Enter the **team ID**, **bundle ID**, **authentication key ID**, and **authentication key (.p8 file)** that you saved from your Apple Developer account. In case your app is signed with a development provisioning profile, enable **Sandbox** mode.
![Apple provider](/images/integrations/push-apns/provider.png)
## Step 3: Test the provider
Follow the [Send push notifications](https://appwrite.io/docs/products/messaging/send-push-notifications) flow to test your provider.
# Read more about APNs and Appwrite Messaging
If you would like to learn more about APNs and Appwrite Messaging, we have some resources that you should visit:
- [Set up the APNs provider in Appwrite Messaging](https://appwrite.io/docs/products/messaging/apns)
- [Send push notifications through Appwrite Messaging](https://appwrite.io/docs/products/messaging/send-push-notifications)
- [Best practices for sending push notifications](https://appwrite.io/blog/post/push-notifications-best-practices)
- [Appwrite Messaging API reference](https://appwrite.io/docs/references/cloud/server-nodejs/messaging)

View File

@@ -0,0 +1,94 @@
---
layout: integration
title: Push notifications with FCM
description: Send customized notifications to your users
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/push-fcm/cover.png
category: Messaging
product:
avatar: '/images/integrations/avatars/fcm.png'
vendor: Firebase
description: 'Firebase Cloud Messaging is a cross-platform messaging solution from Google that enables you to send notifications and messages to users across Android, iOS, and web applications.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/push-fcm/cover.png
- /images/integrations/push-fcm/private-key.png
- /images/integrations/push-fcm/provider.png
---
Firebase Cloud Messaging (FCM) is a cross-platform messaging solution from Google that enables you to send notifications and messages to users across Android, iOS, and web applications. It supports both notification messages displayed by the system UI and data messages handled by your apps code.
# How does the integration work?
You can use the FCM provider in Appwrite Messaging to send push notifications to your users iOS, Android, and web apps. These can be used to send app updates, special offers, instant notifications, reminders, and more.
# How to implement
To implement the FCM provider in Appwrite Messaging, there are several steps you must complete:
## Step 1: Sign up on Firebase
First, you must [sign up for a Firebase account](https://firebase.google.com/) and create a new project. Head to the **Project settings** page, click on the **Service accounts** tab, and **generate new private key**. Download the JSON file for later use.
![Firebase service account private key](/images/integrations/push-fcm/private-key.png)
You must also verify that FCM has been enabled on your project by visiting the **Cloud Messaging** tab. If FCM is disabled, click the three-dots menu, open the link, and click **Enable**.
## Step 2: Add FCM provider to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Messaging** page, click on the **Providers** tab, and **create a new push notifications provider**.
Select **FCM** and upload the JSON file you downloaded from Firebase.
![FCM provider](/images/integrations/push-fcm/provider.png)
## Step 3: Test the provider
To test the provider on mobile apps, there are some additional configuration steps:
{% tabs %}
{% tabsitem #android title="Android with FCM" %}
1. Install the `com.google.firebase:firebase-messaging` Firebase SDK.
2. In your Firebase console, navigate to **Settings** > **General** > **Your apps** > add an **Android** app.
3. Register and download your `google-services.json` config file.
4. Add `google-services.json` at the root of your project.
5. Add Google Services class path to your app-level Gradle dependencies block `"com.google.gms:google-services:4.4.0"`.
6. Add the Google Services plugin to your app-level Gradle in the plugins block as `"com.google.gms.google-services"`.
7. Add notification handler service to `AndroidManifest.xml` inside the application tag, alongside other activities. Find an example of this service in the [Send push notification](https://appwrite.io/docs/products/messaging/send-push-notifications#add-targets) journey.
```xml
<service android:name="<YOUR_NOTIFICATION_HANDLER_SERVICE>" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
```
{% /tabsitem %}
{% tabsitem #ios title="iOS with FCM" %}
1. In your Firebase console, navigate to **Settings** > **General** > **Your apps** > add an **iOS** app.
2. Register and download your `GoogleService-Info.plist` and add it to the root of your project.
3. Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. The key needs **Apple Push Notification Service** enabled.
4. Create a new key, note down the key ID, and download your key.
5. In the Firebase console, go to *Settings*> **Cloud Messaging** > **APNs authentication key** > click **Upload**. Then, upload your key here.
6. Add push notification capability to your app by clicking your root-level app in XCode > **Signing & Capabilities** > + Capabilities > Search for **Push Notifications**.
7. If using SwiftUI, disable swizzling by setting `FirebaseAppDelegateProxyEnabled` to `NO` in your `Info.plist`.
{% /tabsitem %}
{% /tabs %}
After that, you can follow the [Send push notifications](https://appwrite.io/docs/products/messaging/send-push-notifications) flow to test your provider.
# Read more about FCM and Appwrite Messaging
If you would like to learn more about FCM and Appwrite Messaging, we have some resources that you should visit:
- [Set up the FCM provider in Appwrite Messaging](https://appwrite.io/docs/products/messaging/fcm)
- [Send push notifications through Appwrite Messaging](https://appwrite.io/docs/products/messaging/send-push-notifications)
- [Best practices for sending push notifications](https://appwrite.io/blog/post/push-notifications-best-practices)
- [Appwrite Messaging API reference](https://appwrite.io/docs/references/cloud/server-nodejs/messaging)

View File

@@ -0,0 +1,80 @@
---
layout: integration
title: Query MongoDB Atlas
description: Save a document in your MongoDB cluster and list all stored documents
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/query-mongodb/cover.png
category: Databases
product:
avatar: '/images/integrations/avatars/mongodb.png'
vendor: MongoDB
description: 'MongoDB is a popular NoSQL database known for its flexibility and scalability.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/query-mongodb/cover.png
- /images/integrations/query-mongodb/first-cluster.png
- /images/integrations/query-mongodb/connection-string.png
- /images/integrations/query-mongodb/network-access.png
- /images/integrations/query-mongodb/template.png
- /images/integrations/query-mongodb/variables.png
---
MongoDB is a popular NoSQL database known for its flexibility and scalability. It allows developers to store and manage large amounts of data with ease.
# How does the integration work?
You can utilize a pre-built Appwrite function template to integrate a MongoDB Atlas cluster with your app. This will allow you to leverage MongoDB's powerful data management capabilities and NoSQL database and potentially extend it with Appwrites ecosystem.
# How to implement
To implement the MongoDB Atlas integration, follow these simple steps:
## Step 1: Set up a MongoDB database
First, [create an account on MongoDB Atlas](https://www.mongodb.com/cloud/atlas/register) and deploy your first cluster.
![MongoDB Atlas first cluster](/images/integrations/query-mongodb/first-cluster.png)
Create your username and password and copy the **connection string** for your MongoDB Atlas cluster. This connection string will be used to connect the Appwrite Function to your MongoDB cluster.
![MongoDB Atlas connection string](/images/integrations/query-mongodb/connection-string.png)
Next, head to the **Network Access** page from the left sidebar, click on the **Add IP Address** button, and allow access from anywhere.
![MongoDB Atlas network access](/images/integrations/query-mongodb/network-access.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In case you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click on the **Templates** tab, and search for the **MongoDB** function template.
![Function template](/images/integrations/query-mongodb/template.png)
Add the **MongoDB connection string** you saved in the **Variables** step. Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
![Env variables](/images/integrations/query-mongodb/variables.png)
## Step 3: Test the function
Once the function is ready, visit the **Domains** tab on the **Functions** page and copy the domain URL to test the function. Sending a GET (HTTP) Request to this endpoint will add a randomly generated mock document and list all the documents in the database.
```bash
curl DEPLOYED_FUNCTION_DOMAIN \
-H 'accept: application/json'
```
You can add other database functionalities by editing the function generated for you on GitHub.
# Read more about MongoDB Atlas and Appwrite Functions
If you would like to learn more about MongoDB Atlas and Appwrite Functions, we have some resources that you should visit:
- [Integrate SQL, NoSQL, Vector, Graph, or any database into your Appwrite project](https://appwrite.io/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project)
- [Understanding data queries in database management](https://appwrite.io/blog/post/understand-data-queries)
- [Appwrite Functions docs](https://appwrite.io/docs/products/functions)

View File

@@ -0,0 +1,69 @@
---
layout: integration
title: Query Upstash
description: Store data in your Upstash vector database and query it for similar data
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/query-upstash/cover.png
category: Databases
product:
avatar: '/images/integrations/avatars/upstash.png'
vendor: Upstash
description: 'Upstash Vector provides a powerful vector database designed to handle complex queries and search functionalities.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/query-upstash/cover.png
- /images/integrations/query-upstash/index.png
- /images/integrations/query-upstash/template.png
- /images/integrations/query-upstash/variables.png
---
Upstash Vector provides a powerful vector database designed to handle complex queries and search functionalities. Its ideal for applications that require fast and efficient handling of vector data.
# How does the integration work?
You can utilize a pre-built Appwrite function template to integrate an Upstash Vector database with your app. This setup enables you to store and query vector data efficiently, enhancing your application's search and recommendation features.
# How to implement
To implement the Upstash Vector integration, follow these simple steps:
### Step 1: Set up the Upstash Vector database
First, [create an account on Upstash](https://console.upstash.com/login) and set up a **new Vector index** with your preferred region and embedding model. Once it is ready, copy your **endpoint** and **token** from the indexs dashboard for further usage
![Upstash vector index](/images/integrations/query-upstash/index.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Upstash** function template.
![Function template](/images/integrations/query-upstash/template.png)
Add the **Upstash endpoint** and **token** you saved in the **Variables** step. Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
![Env variables](/images/integrations/query-upstash/variables.png)
## Step 3: Test the function
Once the function is ready, visit the **Domains** tab on the **Functions** page and copy the domain URL to test the function. Sending a GET (HTTP) Request to this endpoint will add a randomly generated mock embedding and query for the one most similar entry in the database.
```bash
curl DEPLOYED_FUNCTION_DOMAIN \
-H 'accept: application/json'
```
You can add other database functionalities by editing the function generated on GitHub.
# Read more about Upstash and Appwrite Functions
If you would like to learn more about Upstash and Appwrite Functions, we have some resources that you should visit:
- [Integrate SQL, NoSQL, Vector, Graph, or any database into your Appwrite project](https://appwrite.io/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project)
- [Appwrite Functions docs](https://appwrite.io/docs/products/functions)

View File

@@ -0,0 +1,84 @@
---
layout: integration
title: Search with Algolia
description: Integrate Algolia search into your Appwrite database
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/search-algolia/cover.png
category: Search
product:
avatar: '/images/integrations/avatars/algolia.png'
vendor: Algolia
description: 'Algolia is a search platform that helps you add fast and relevant search capabilities to your app.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/search-algolia/cover.png
- /images/integrations/search-algolia/overview.png
- /images/integrations/search-algolia/index.png
- /images/integrations/search-algolia/template.png
- /images/integrations/search-algolia/variables.png
- /images/integrations/search-algolia/demo.png
---
Algolia is a search platform that helps you add fast and relevant search capabilities to your app. It makes it easy to find and explore data quickly.
# How does the integration work?
By integrating Algolia with Appwrite, you can use Algolia's search features directly in your Appwrite database. This lets you leverage Algolias comprehensive search capabilities with your Appwrite backend.
# How to implement
To implement the Algolia integration, follow these simple steps:
## Step 1: Set up an Algolia account
First, [sign up on Algolia](https://dashboard.algolia.com/users/sign_up) and create a new application. Save the **Application ID**, **Search API Key**, and **Write API Key** for further usage.
![Algolia overview](/images/integrations/search-algolia/overview.png)
Then, click on the **Search** page from the left sidebar and **create a new Index** to store your searchable data. Save your **Index ID** for further usage.
![New index](/images/integrations/search-algolia/index.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In case you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates. Additionally, for this template, you must have an Appwrite Database and Collection filled with data in advance.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Algolia** function template.
![Function template](/images/integrations/search-algolia/template.png)
During the setup process, click on the checkbox to create an Appwrite API key on completion and add the Appwrite Database ID and Collection ID for the data you want to index and search as well as the **Algolia application ID**, **search API key**, **write API key** (under Admin API Key), and **index ID** in the **Variables** step. If you are self-hosting Appwrite, click on the **optional variables** dropdown and update the Appwrite endpoint to your instances publicly accessible endpoint.
![Env variables](/images/integrations/search-algolia/variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic.
## Step 3: Test the function
Once all the steps are complete, it is time to test the function! Before we go further, visit the **Domains** tab on the **Functions** page and copy the domain URL to test the function.
Send a POST (HTTP) Request to the function URL to index the Appwrite Collection in Algolia.
```bash
curl -XPOST https://DEPLOYED_FUNCTION_DOMAIN
```
In case you have a large collection of data and your function executions timeout, you can head to the **Settings** tab on the **Functions** page and increase the function timeout limit from **15 seconds** to **900 seconds** (maximum).
Then, open your function URL in the browser to try the interactive search UI.
![Demo](/images/integrations/search-algolia/demo.png)
# Read more about Algolia
If you would like to learn more about Algolia, we have some resources that you should visit:
- [Sign up for Algolia](https://dashboard.algolia.com/users/sign_up)
- [Learn more about Functions templates in Appwrite docs](https://appwrite.io/docs/products/functions/templates)
- [Connect with other developers and the Appwrite team on Discord.](https://discord.com/invite/appwrite)

View File

@@ -0,0 +1,72 @@
---
layout: integration
title: SMS with Twilio
description: Send customized SMS messages to your users
date: 2024-07-30
featured: true
isPartner: true
isNew: true
cover: /images/integrations/sms-twilio/cover.png
category: Messaging
product:
avatar: '/images/integrations/avatars/twilio.png'
vendor: Twilio
description: 'Twilio is a cloud communications platform that provides programmable communication tools using web APIs and SDKs.'
platform:
- 'Self-hosted'
images:
- /images/integrations/sms-twilio/cover.png
- /images/integrations/sms-twilio/twilio-console.png
- /images/integrations/sms-twilio/config.png
- /images/integrations/sms-twilio/sms.png
---
Twilio is a cloud communications platform that provides programmable communication tools for making and receiving phone calls, sending and receiving text messages, and performing other communication functions using web APIs and SDKs.
# How does the integration work?
You can use the Twilio provider in Appwrite Messaging to send customized SMS messages to your users. These SMS messages can be sent immediately or scheduled. You can send SMS messages for purposes like reminders, promotions, announcements, and even custom authentication flows.
# How to implement
To implement the Twilio provider in Appwrite Messaging, there are several steps you must complete:
## Step 1: Sign up on Twilio
First, you must [sign up for a Twilio account](https://www.twilio.com/try-twilio), upgrade your account (in case you want to message numbers other than your own), and purchase a phone number with the SMS capability.
![Twilio console](/images/integrations/sms-twilio/twilio-console.png)
Ensure you save the following information for later use:
| Field name | |
| --- | --- |
| Account SID | Head to **Twilio console** > **Account info** > **Account SID**. |
| Auth token | Head to **Twilio console** > **Account info** > **Auth Token**. |
| Phone number | You can access numbers by navigating to your **Twilio console** > **Develop** > **Phone Numbers** > **Manage** > **Active Numbers**. |
## Step 2: Add Twilio provider to your Appwrite project
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In your Appwrite project, head over to the **Messaging** page, click on the **Providers** tab, and **create a new SMS provider**.
Select **Twilio** and add the **account SID**, **auth token**, and **phone number** that you saved from the Twilio console.
![Twilio provider config](/images/integrations/sms-twilio/config.png)
## Step 3: Test the Twilio provider
Before you proceed, you must already have at least one [topic](https://appwrite.io/docs/products/messaging/topics) or [target](https://appwrite.io/docs/products/messaging/targets) set up.
Once the provider is set up, you can go to the **Messages** tab on the **Messaging** page and **create an SMS message**. You can add the test message, configure the users to send the message to, and pick when the message should be sent out.
![SMS message console](/images/integrations/sms-twilio/sms.png)
# Read more about Twilio and Appwrite Messaging
If you would like to learn more about Twilio and Appwrite Messaging, we have some resources that you should visit:
- [Sign up for Twilio](https://www.twilio.com/try-twilio)
- [Set up the Twilio provider in Appwrite Messaging](https://appwrite.io/docs/products/messaging/twilio)
- [Send SMS messages through Appwrite Messaging](https://appwrite.io/docs/products/messaging/send-sms-messages)
- [How tools like Twilio can simplify messaging for developers](https://appwrite.io/blog/post/simplify-messaging-twilio)
- [Appwrite Messaging API reference](https://appwrite.io/docs/references/cloud/server-nodejs/messaging)

View File

@@ -0,0 +1,84 @@
---
layout: integration
title: Storage with Amazon S3
description: Store files in Amazon S3 instead of your local storage device
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/storage-s3/cover.png
category: Storage
product:
avatar: '/images/integrations/avatars/aws.png'
vendor: AWS
description: 'Amazon S3 is an object storage service that offers industry-leading scalability, data availability, security, and performance.'
platform:
- 'Self-hosted'
images:
- /images/integrations/storage-s3/cover.png
- /images/integrations/storage-s3/bucket.png
- /images/integrations/storage-s3/access-key.png
- /images/integrations/storage-s3/appwrite-file.png
- /images/integrations/storage-s3/s3-file.png
---
Amazon S3 (Simple Storage Service) is an object storage service that offers industry-leading scalability, data availability, security, and performance. You can use Amazon S3 to store and protect any amount of data for a range of use cases, such as data lakes, websites, mobile applications, backup and restore, archive, enterprise applications, IoT devices, and big data analytics.
# How does the integration work?
If you are using self-hosting Appwrite, you can use the Amazon S3 integration for Appwrite Storage to store your files in an S3 bucket instead of on your local hard drive. This is beneficial if you expect large volumes of data or the need to have scalable data storage for your self-hosted Appwrite instance.
# How to implement
To implement the Amazon S3 provider for Appwrite Storage, there are several steps you must complete:
## Step 1: Sign up on AWS
First, you must [sign up for an AWS account](https://signin.aws.amazon.com/signup?request_type=register) and create an S3 bucket. Save the **Bucket name** and **AWS Region** mentioned here for later use.
![Create S3 bucket](/images/integrations/storage-s3/bucket.png)
To access this bucket from Appwrite Storage, we also need to generate an access key within our AWS account. To do so, click on your username in the top-right corner, click on **Security credentials**, and scroll below to create an access key. Save your **Access key ID** and **Secret access key** for later usage.
![Create AWS access key](/images/integrations/storage-s3/access-key.png)
## Step 2: Add S3 provider to your Appwrite instance
For this step, you must [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already.
Visit the `.env` file created for your Appwrite instance and update the following environment variables:
```bash
_APP_STORAGE_DEVICE=s3
_APP_STORAGE_S3_BUCKET=[BUCKET_NAME]
_APP_STORAGE_S3_REGION=[AWS_REGION]
_APP_STORAGE_S3_ACCESS_KEY=[ACCESS_KEY_ID]
_APP_STORAGE_S3_SECRET=[SECRET_ACCESS_KEY]
```
After that, run the following Docker Compose commands in your terminal to restart your Appwrite containers and verify if the changes have been successfully applied:
```bash
docker compose up -d --force-recreate
docker compose exec appwrite vars
```
## Step 3: Test the provider
To test your S3, open your Appwrite project, go to the Storage page, create a new bucket, and upload a file.
![File on Appwrite Storage](/images/integrations/storage-s3/appwrite-file.png)
When you visit your S3 bucket via the AWS Management Console, you should see the same file uploaded there.
![File on Amazon S3](/images/integrations/storage-s3/s3-file.png)
# Read more about S3 and Appwrite Storage
If you would like to learn more about Amazon S3 and Appwrite Auth, we have some resources that you should visit:
- [What is Amazon S3?](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html)
- [How to create an Amazon S3 bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html)
- [Appwrite self-hosting docs](https://appwrite.io/docs/advanced/self-hosting)
- [Storage environment variables for Appwrite (self-hosted)](https://appwrite.io/docs/advanced/self-hosting/environment-variables#storage)
- [Appwrite Storage API reference](https://appwrite.io/docs/references/cloud/client-web/storage)

View File

@@ -0,0 +1,100 @@
---
layout: integration
title: Payments with Stripe
description: Receive payments and store paid orders
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/stripe-payments/cover.png
category: Payments
product:
avatar: '/images/integrations/avatars/stripe.png'
vendor: Stripe
description: 'Stripe is an online payment processing platform that allows businesses to accept online payments securely and efficiently.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/stripe-payments/cover.png
- /images/integrations/stripe-payments/dashboard.png
- /images/integrations/stripe-payments/api-keys.png
- /images/integrations/stripe-payments/webhooks.png
- /images/integrations/stripe-payments/template.png
- /images/integrations/stripe-payments/variables.png
- /images/integrations/stripe-payments/web-platform.png
- /images/integrations/stripe-payments/demo.png
- /images/integrations/stripe-payments/database.png
---
Stripe is an online payment processing platform that allows businesses to accept online payments securely and efficiently. Stripe supports a variety of payment methods, including credit cards, debit cards, and digital wallets, and offers additional services such as billing, invoicing, and fraud prevention.
With robust APIs and extensive documentation, Stripe enables developers to integrate its payment solutions into websites and mobile applications seamlessly, making it a popular choice for businesses of all sizes.
# How does the integration work?
You can utilize a pre-built Appwrite function template to enable payments via Stripe in your app. You can then use this to ship packages, send PDF books, give access to video courses, or anything else your business needs.
# How to implement
To implement the Stripe payments integration, there are several steps you must complete:
## Step 1: Set up Stripe
First, [sign up for Stripe](https://stripe.com/) and open the dashboard in test mode.
![Stripe dashboard](/images/integrations/stripe-payments/dashboard.png)
Head to the **Developers** page from the navbar and click on the **API keys** tab. Save the **Secret key** for further usage.
![Stripe API keys](/images/integrations/stripe-payments/api-keys.png)
Then, go to the **Webhooks** tab, select the event `checkout.session.completed`, and add a temporary endpoint `https://temporary-endpoint` (we will replace this with our final endpoint later). Save the **webhook signing secret** for later usage.
![Stripe webhooks](/images/integrations/stripe-payments/webhooks.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Payments with Stripe** function template.
![Function template](/images/integrations/stripe-payments/template.png)
During the setup process, click the checkbox to generate an Appwrite API key on completion and add the **Stripe secret key** and **webhook secret** in the **Variables** step. If you are self-hosting Appwrite, click on the **optional variables** dropdown and update the Appwrite endpoint to your instances publicly accessible endpoint.
![Env variables](/images/integrations/stripe-payments/variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic. Once the function is deployed, go to the **Settings** tab on the **Function** page, scroll down to your **Build settings**, and update the commands to the following (and then redeploy the function):
```bash
npm install
npm run setup
```
Then, go to the **Domains** tab, copy the domain, and update it in your **Stripe webhook details** in the following format:
```bash
https://DEPLOYED_FUNCTION_DOMAIN/webhook
```
## Step 3: Test the function
Once all the steps are complete, it is time to test the function! First, copy the function URL, go to the **Appwrite project dashboard**, and add it to the **Platforms** section as a web app. This will register your function URL as an authorized hostname to interact with Appwrite (to prevent CORS).
![Add web platform](/images/integrations/stripe-payments/web-platform.png)
Then, open it in your browser to test the function and access the pre-built interactive UI. You can anonymously log in through this UI and create a payment order using [Stripes test card number](https://docs.stripe.com/testing#cards). As soon as this process is completed, the function UI will show you the completed order.
![Demo](/images/integrations/stripe-payments/demo.png)
You can visit the **Databases** page in your Appwrite project, enter the `orders` database and the `orders` collection within that, and find your orders.
![Appwrite database](/images/integrations/stripe-payments/database.png)
# Read more about Stripe Payments and Appwrite Functions
If you would like to learn more about Stripe Payments and Appwrite Functions, we have some resources that you should visit:
- [Sign up on Stripe](https://stripe.com)
- [Learn more about Functions templates in Appwrite docs](https://appwrite.io/docs/products/functions/templates)

View File

@@ -0,0 +1,94 @@
---
layout: integration
title: Subscriptions with Stripe
description: Receive recurring payments and grant subscribers extra permissions
date: 2024-07-30
featured: true
isPartner: true
isNew: true
cover: /images/integrations/stripe-subscriptions/cover.png
category: Payments
product:
avatar: '/images/integrations/avatars/stripe.png'
vendor: Stripe
description: 'Stripe is an online payment processing platform that allows businesses to accept online payments securely and efficiently.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/stripe-subscriptions/cover.png
- /images/integrations/stripe-subscriptions/dashboard.png
- /images/integrations/stripe-subscriptions/api-keys.png
- /images/integrations/stripe-subscriptions/webhooks.png
- /images/integrations/stripe-subscriptions/template.png
- /images/integrations/stripe-subscriptions/variables.png
- /images/integrations/stripe-subscriptions/web-platform.png
- /images/integrations/stripe-subscriptions/demo.png
- /images/integrations/stripe-subscriptions/user.png
---
Stripe is an online payment processing platform that allows businesses to accept online payments securely and efficiently. Stripe supports a variety of payment methods, including credit cards, debit cards, and digital wallets, and offers additional services such as billing, invoicing, and fraud prevention.
With robust APIs and extensive documentation, Stripe enables developers to integrate its payment solutions into websites and mobile applications with ease, making it a popular choice for businesses of all sizes.
# How does the integration work?
You can utilize a pre-built Appwrite function template to enable paid subscriptions via Stripe in your app. This will allow you to accept recurring payments from your customers and grant them extra permissions.
# How to implement
To implement the Stripe subscriptions integration, there are several steps you must complete:
## Step 1: Setup Stripe
First, [sign up for Stripe](https://stripe.com/) and open the dashboard in test mode.
![Stripe dashboard](/images/integrations/stripe-subscriptions/dashboard.png)
Head to the **Developers** page from the navbar and click on the **API keys** tab. Save the **Secret key** for further usage.
![Stripe API keys](/images/integrations/stripe-subscriptions/api-keys.png)
Then, go to the **Webhooks** tab, select the events `customer.subscription.created` and `customer.subscription.deleted`, and add a temporary endpoint `https://temporary-endpoint` (we will replace this with our final endpoint later). Save the **webhook signing secret** for later usage.
![Stripe webhooks](/images/integrations/stripe-subscriptions/webhooks.png)
## Step 2: Create the Appwrite Function
For this step, you must [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. If you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
Head over to the Appwrite console, navigate to the **Functions** page, click the **Templates** tab, and search for the **Subscriptions with Stripe** function template.
![Function template](/images/integrations/stripe-subscriptions/template.png)
During the setup process, click the checkbox to generate an Appwrite API key on completion and add the **Stripe secret key** and **Webhook secret** in the **Variables** step. If you are self-hosting Appwrite, click the **optional variables** dropdown and update the Appwrite endpoint to your instances publicly accessible endpoint.
![Env variables](/images/integrations/stripe-subscriptions/variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic. Once the function is deployed, go to the **Domains** tab on the **Function** page, copy the domain, and update it in your **Stripe webhook details** in the following format:
```bash
https://DEPLOYED_FUNCTION_DOMAIN/webhook
```
## Step 3: Test the function
Once all the steps are complete, it is time to test the function! First, copy the function URL, go to the **Appwrite project dashboard**, and add it to the **Platforms** section as a web app. This will register your function URL as an authorized hostname to interact with Appwrite (to prevent CORS).
![Add web platform](/images/integrations/stripe-subscriptions/web-platform.png)
Then, open it in your browser to test the function and access the pre-built interactive UI. You can anonymously log in through this UI and create a subscription using [Stripes test card number](https://docs.stripe.com/testing#cards). As soon as this process is complete, the function UI will show that you are subscribed.
![Demo](/images/integrations/stripe-subscriptions/demo.png)
Additionally, your user on Appwrite will feature the `subscriber` label, which you can verify by visiting the **Auth** page in your Appwrite project and clicking on the user.
![Appwrite user](/images/integrations/stripe-subscriptions/user.png)
# Read more about Stripe Subscriptions and Appwrite Functions
If you would like to learn more about Stripe Subscriptions and Appwrite Functions, we have some resources that you should visit:
- [Sign up on Stripe](https://stripe.com)
- [Add app subscriptions with Stripe on Appwrite](https://appwrite.io/docs/tutorials/subscriptions-with-stripe/step-1)
- [Learn more about Functions templates in Appwrite docs](https://appwrite.io/docs/products/functions/templates)

View File

@@ -0,0 +1,356 @@
<script lang="ts">
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { Main } from '$lib/layouts';
import { TITLE_SUFFIX } from '$routes/titles';
import FooterNav from '../../../lib/components/FooterNav.svelte';
import MainFooter from '../../../lib/components/MainFooter.svelte';
import { socials } from '$lib/constants';
import { anyify } from '$lib/utils/anyify';
//import BlobPink from "$routes/startups/(assets)/blob-pink.svg";
// import BlobPinkMobile from "$routes/startups/(assets)/blob-pink-mobile.svg";
import Pink from './bg.png';
let email = '';
let name = '';
let companyName = '';
let companySize: string | null = null;
let companyWebsite = '';
let integrationStatus: string | null = null;
let linkToDocumentation = '';
let productUrl = '';
let extraDetails = '';
let subject = '';
let message = '';
let hasCreatedIntegration = false;
let error: string | undefined;
let submitted = false;
async function handleSubmit() {
error = undefined;
message = `Name of representative: ${name}\n\nWork Email: ${email}\n\nCompany Name: ${companyName}\n\nCompany Size: ${companySize}\n\nCompany Website: ${companyWebsite}\n\nIntegration status: ${integrationStatus}\n\nLink to Documentation: ${linkToDocumentation}\n\nLink to product/company assets: ${productUrl}\n\nDetails: ${extraDetails}`;
subject = `Technology Partner Application: ${companyName}`;
const response = await fetch('https://growth.appwrite.io/v1/feedback', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
firstName: name,
subject,
message
})
});
if (response.status >= 400) {
error = response.status >= 500 ? 'Server Error.' : 'Error submitting form.';
return;
}
submitted = true;
}
const title = 'Become a Technology Partner' + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
</script>
<svelte:head>
<!-- Titles -->
<title>{title}</title>
<meta property="og: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} />
<!-- Image -->
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
</svelte:head>
<div class="u-position-absolute" style="pointer-events:none;">
<img src={Pink} alt="" />
</div>
<Main>
<div class="web-big-padding-section">
<div id="form" class="web-big-padding-section-level-1 u-padding-0 u-overflow-hidden">
<div
class="web-big-padding-section-level-2 is-margin-replace-padding u-position-relative"
>
<div class="u-position-relative">
<div class="web-container u-position-relative">
<!-- before submit -->
<div
class="u-position-relative u-z-index-1 web-grid-1-1-opt-2 u-gap-32 e-u-row-gap-0"
>
<div>
<div
class="web-u-max-inline-size-none-mobile"
class:web-u-max-width-380={!submitted}
>
{#if submitted}
<section class="u-flex-vertical web-u-gap-20">
<h1 class="web-display web-u-color-text-primary">
Thank you for applying
</h1>
<p class="web-description web-u-padding-block-end-32">
Your application has been sent successfully. Our
team will try to get back to you as soon as
possible.
</p>
<a
href="/integrations"
class="web-button is-secondary web-u-margin-block-end-32"
>
<span>Back to integrations</span>
</a>
</section>
{:else}
<section class="u-flex-vertical web-u-gap-20">
<h4 class="web-display web-u-color-text-primary">
Become a Technology Partner
</h4>
<p class="web-description">
Apply to our Technology Partners Program by filling
out this form. Our team will reach out to you to
confirm your application was accepted.
</p>
</section>
{/if}
<section
class="u-flex-vertical u-gap-12 u-padding-block-start-40 u-margin-block-start-40 web-u-sep-block-start"
>
<h2 class="web-label web-u-color-text-primary">
Follow us
</h2>
<ul class="u-flex u-gap-8">
{#each socials as social}
<li>
<a
href={social.link}
class="web-icon-button"
aria-label={social.label}
target="_blank"
rel="noopener noreferrer"
>
<span
class={social.icon}
aria-hidden="true"
/>
</a>
</li>
{/each}
</ul>
</section>
<div
class="web-is-only-mobile web-u-margin-block-start-40 web-u-padding-block-start-40 web-u-sep-block-start"
/>
</div>
</div>
{#if !submitted}
<form
method="post"
on:submit|preventDefault={handleSubmit}
class="u-flex-vertical u-gap-16"
>
<div class="u-flex u-main-end">
<ul
class="web-form-list is-two-columns u-gap-16 u-width-full-line web-u-max-width-580 web-u-max-inline-size-none-mobile"
>
<li class="web-form-item u-flex-vertical u-gap-4">
<label class="u-block" for="name"
>Name of representative</label
>
<input
required
class="web-input-text"
type="text"
placeholder="Walter O'Brien"
id="name"
bind:value={name}
/>
</li>
<li class="web-form-item u-flex-vertical u-gap-4">
<label class="u-block" for="workEmail"
>Work email address</label
>
<input
required
class="web-input-text"
type="email"
placeholder="walter@appwrite.io"
id="workEmail"
bind:value={email}
/>
</li>
<li class="web-form-item u-flex-vertical u-gap-4">
<label class="u-block" for="companyName"
>Company name</label
>
<input
required
class="web-input-text"
type="text"
placeholder="Acme Corp"
id="companyName"
bind:value={companyName}
/>
</li>
<li class="web-form-item u-flex-vertical u-gap-4">
<label class="u-block" for="companySize"
>Company size</label
>
<div class="u-position-relative">
<select
class="web-input-text"
id="companySize"
bind:value={companySize}
>
<option value={null}>Select size</option>
<option>1-10 employees</option>
<option>11-50 employees</option>
<option>51-200 employees</option>
<option>201-500 employees</option>
<option>501-1000 employees</option>
<option>1001-5000 employees</option>
<option>5000+ employees</option>
</select>
<span
class="icon-cheveron-down u-position-absolute u-inset-inline-end-8 u-inset-block-start-8 web-u-pointer-events-none"
aria-hidden="true"
></span>
</div>
</li>
<li
class="web-form-item is-column-span-2 u-flex-vertical u-gap-4"
>
<label class="u-block" for="companyWebsite"
>Company website</label
>
<input
required
class="web-input-text"
type="url"
placeholder="https://appwrite.io"
id="companyWebsite"
bind:value={companyWebsite}
/>
</li>
<li
class="web-form-item is-column-span-2 u-flex-vertical u-gap-4"
>
<label class="u-block" for="integration"
>Have you already created an integration with
Appwrite?</label
>
<div class="u-position-relative">
<select
class="web-input-text"
id="integration"
bind:value={integrationStatus}
on:change={(e) =>
anyify(e.target).value === 'yes'
? (hasCreatedIntegration = true)
: (hasCreatedIntegration = false)}
>
<option value={null}>Select</option>
<option value="yes"
>Yes, we have already created an
integration</option
>
<option value="no"
>No, it is currently in the process of
being built</option
>
<option value="notYet"
>No, we have yet to start building</option
>
</select>
<span
class="icon-cheveron-down u-position-absolute u-inset-inline-end-8 u-inset-block-start-8 web-u-pointer-events-none"
aria-hidden="true"
></span>
</div>
</li>
{#if hasCreatedIntegration}
<li
class="web-form-item is-column-span-2 u-flex-vertical u-gap-4"
>
<label class="u-block" for="linkToDocumentation"
>Link to the integration's documentation</label
>
<input
required
class="web-input-text"
type="url"
placeholder="https://appwrite.io/docs"
id="linkToDocumentation"
bind:value={linkToDocumentation}
/>
</li>
{/if}
<li
class="web-form-item is-column-span-2 u-flex-vertical u-gap-4"
>
<label class="u-block" for="productUrl"
>Link to the product/company's brand assets</label
>
<input
required
class="web-input-text"
type="url"
placeholder="https://appwrite.io/assets"
id="productUrl"
bind:value={productUrl}
/>
</li>
<li
class="web-form-item is-column-span-2 u-flex-vertical u-gap-4"
>
<label class="u-block" for="details"
>Any other details you'd like to share with us?</label
>
<textarea
required
class="web-input-text"
placeholder="Your message"
id="details"
bind:value={extraDetails}
></textarea>
</li>
</ul>
</div>
<div
class="u-flex u-gap-16 u-main-space-between web-u-flex-vertical-reverse-mobile"
>
<p class="web-caption-400 web-u-max-width-380">
{#if error}
{error}
{/if}
</p>
<button
type="submit"
class="web-button u-cross-child-center web-u-inline-width-100-percent-mobile-break1"
>
<span>Submit</span>
</button>
</div>
</form>
{/if}
</div>
</div>
<div class="web-container">
<FooterNav />
<MainFooter />
</div>
</div>
</div>
</div>
</div>
</Main>

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 KiB

View File

@@ -0,0 +1,79 @@
---
layout: integration
title: WhatsApp with Vonage
description: Send automated replies to messages on WhatsApp
date: 2024-07-30
featured: false
isPartner: true
isNew: true
cover: /images/integrations/whatsapp-vonage/cover.png
category: Messaging
product:
avatar: '/images/integrations/avatars/vonage.png'
vendor: Vonage
description: 'Vonage is a cloud communications provider that offers residential telecommunications services based on voice over Internet Protocol as well as programmable communications tools via web APIs.'
platform:
- 'Self-hosted'
- 'Cloud'
images:
- /images/integrations/whatsapp-vonage/cover.png
- /images/integrations/whatsapp-vonage/settings.png
- /images/integrations/whatsapp-vonage/template.png
- /images/integrations/whatsapp-vonage/variables.png
- /images/integrations/whatsapp-vonage/demo.png
---
Vonage is a cloud communications provider that offers residential telecommunications services based on voice over Internet Protocol as well as programmable communications tools such as phone calls, SMSes, WhatsApp messages, etc. via web APIs.
# How does the integration work?
You can use a pre-built Appwrite Function template that is integrated with Vonage to build a WhatsApp-based chatbot that can accept your messages and respond based on pre-defined logic.
# How to implement
To implement the **WhatsApp with Vonage** Appwrite Function template, there are several steps you must complete:
## Step 1: Sign up on Vonage
First, [sign up for a Vonage account](https://ui.idp.vonage.com/ui/auth/registration) to use the Vonage Communications APIs. This will create a trial account and give you access to the Vonage API dashboard.
![Vonage API settings](/images/integrations/whatsapp-vonage/settings.png)
Ensure you save the following information for later use:
| Field name | |
| --- | --- |
| API key | Head to the **Vonage API dashboard** > **API Settings** > **API key** |
| API secret | Head to the **Vonage API dashboard** > **API Settings** > **API secret** |
| Signature secret | Head to the **Vonage API dashboard** > **API Settings** > **Signature secret** |
| WhatsApp phone number | Head to the **Vonage API dashboard** > **Developer Tools** > **Messages API Sandbox** > enable **WhatsApp** and copy phone number |
Once the Appwrite Function is deployed, we will return here to add the Function URL as the **Inbound Webhook** link.
## Step 2: Create the Appwrite Function
For this step, [create an account on Appwrite Cloud](https://cloud.appwrite.io/register) or [self-host Appwrite](https://appwrite.io/docs/advanced/self-hosting) if you havent already. In case you decide to self-host Appwrite, there are [additional setup steps](https://appwrite.io/docs/advanced/self-hosting/functions) to use Appwrite Function templates.
In your Appwrite project, go to the **Functions** page, click on the **Templates** tab, search for Vonage, and select the **WhatsApp with Vonage** function template.
![Function template](/images/integrations/whatsapp-vonage/template.png)
During the setup process, add the Vonage **API key**, **API secret, signature secret**, and **WhatsApp phone number** in the **Variables** step**.**
![Env variables](/images/integrations/whatsapp-vonage/variables.png)
Then, create a new repository with the default branch and root directory settings. You can edit this repository later to update the function logic. Once the function is ready, visit the **Domains** tab on the function page and copy the domain to add to the **Inbound Webhook** link on the **Messages API Sandbox** page on your Vonage account.
## Step 3: Test the integration
Open **WhatsApp** on your phone, join the Vonage WhatsApp Channel (via the steps mentioned on the *Messaging API Sandbox* on *Vonage*), and send any message to the WhatsApp number. You shall receive a message in the format: `Hi there! You sent me: <SENT MESSAGE>`
![demo](/images/integrations/whatsapp-vonage/demo.png)
# Read more about Vonage and Appwrite
If you would like to learn more about Vonage, we have some resources that you should visit:
- [Sign up for Vonage](https://ui.idp.vonage.com/ui/auth/registration)
- [Send WhatsApp messages with Vonage and Appwrite Functions](https://appwrite.io/blog/post/function-template-whatsapp-vonage)
- [Appwrite Functions products docs](https://appwrite.io/docs/products/functions)

View File

@@ -1,16 +1,16 @@
<script lang="ts">
import { FooterNav, MainFooter, PreFooter } from "$lib/components";
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from "$lib/utils/metadata";
import { FooterNav, MainFooter, PreFooter } from '$lib/components';
import { DEFAULT_HOST } from '$lib/utils/metadata';
import { Main } from "$lib/layouts";
import { TITLE_SUFFIX } from "$routes/titles";
import ComparePlans from "./compare-plans.svelte";
import Faq from "./faq.svelte";
import BG from "./bg.png?enhanced";
import { Main } from '$lib/layouts';
import { TITLE_SUFFIX } from '$routes/titles';
import ComparePlans from './compare-plans.svelte';
import Faq from './faq.svelte';
import BG from './bg.png?enhanced';
const title = "Pricing" + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const ogImage = DEFAULT_HOST + "/images/open-graph/website.png";
const title = 'Pricing' + TITLE_SUFFIX;
const description = 'Explore our straightforward pricing plans that scale with your project.';
const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
</script>
<svelte:head>
@@ -101,7 +101,8 @@
<li><span>No Add-ons</span></li>
<li>
<span
>1 Database, 3 Buckets, 5 Functions per project</span
>1 Database, 3 Buckets, 5 Functions per
project</span
>
</li>
</ul>
@@ -121,10 +122,12 @@
>
$15
</div>
<div class="u-margin-block-start-4">per member/month</div>
<div class="u-margin-block-start-4">
per member/month
</div>
<p class="web-main-body-500 u-margin-block-start-16">
For pro developers and teams that need to scale their
products.
For pro developers and teams that need to scale
their products.
</p>
<a
href="https://cloud.appwrite.io/console?type=createPro"
@@ -149,7 +152,8 @@
<li><span>Removable Appwrite branding</span></li>
<li><span>Add-ons</span></li>
<li>
<span>Unlimited Databases, Buckets and Functions</span
<span
>Unlimited Databases, Buckets and Functions</span
>
</li>
</ul>
@@ -220,8 +224,8 @@
<div class="web-inline-tag is-pink">Coming Soon</div>
</header>
<p class="u-margin-block-start-8">
Large scale projects seeking greater performance,
collaboration and security.
Large scale projects seeking greater performance, collaboration
and security.
</p>
<a
href="/contact-us"

View File

@@ -1,5 +1,6 @@
---
layout: policy
description: Understand how we collect, use, and protect your personal information.
title: Privacy Policy
---
This privacy policy (“Privacy Policy”) governs how we, Appwrite Code Ltd. (together, “Appwrite” “we”, “our” or “us”) use, collect and store Personal Data we collect or receive from or about you (“you”) such as in the following use cases:
@@ -329,7 +330,7 @@ How we protect and retain your personal data
We have implemented appropriate technical, organizational and security measures designed to protect your Personal Data. However, please note that we cannot guarantee that the information will not be compromised as a result of unauthorized penetration to our servers. As the security of information depends in part on the security of the computer, device or network you use to communicate with us and the security you use to protect your user IDs and passwords, please make sure to take appropriate measures to protect this information.
{% count_title title="Retention of your personal data" / %}
Your Personal Data will be stored until we delete the record and we proactively delete it or you send a valid deletion request, please note that in some circumstances we may store your Personal Data for longer periods of time, for example (i) where we are required to do so in accordance with legal, regulatory, tax or accounting requirements, or (ii) for us to have an accurate record of your dealings with us in the event of any complaints or challenges, or (iii) if we reasonably believe there is a prospect of litigation relating to your Personal Data or dealings. Regaioention of cookies, you can read more in our cookie policy [https://appwrite.io/policy/cookies](https://appwrite.io/policy/cookies).
Your Personal Data will be stored until we delete the record and we proactively delete it or you send a valid deletion request, please note that in some circumstances we may store your Personal Data for longer periods of time, for example (i) where we are required to do so in accordance with legal, regulatory, tax or accounting requirements, or (ii) for us to have an accurate record of your dealings with us in the event of any complaints or challenges, or (iii) if we reasonably believe there is a prospect of litigation relating to your Personal Data or dealings. Regarding retention of cookies, you can [read more in our cookie policy](https://appwrite.io/policy/cookies).
{% /count_section %}
{% count_section %}

View File

@@ -1,21 +1,22 @@
<script>
import { FooterNav, MainFooter, PreFooter } from "$lib/components";
import Main from "$lib/layouts/Main.svelte";
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from "$lib/utils/metadata";
import { TITLE_SUFFIX } from "$routes/titles";
import Draft from "./(components)/Draft.svelte";
import Schedule from "./(components)/Schedule.svelte";
import Send from "./(components)/Send.svelte";
import Target from "./(components)/Target.svelte";
import MultiCodeContextless from "./(components)/MultiCodeContextless.svelte";
import { FooterNav, MainFooter, PreFooter } from '$lib/components';
import Main from '$lib/layouts/Main.svelte';
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
import { TITLE_SUFFIX } from '$routes/titles';
import Draft from './(components)/Draft.svelte';
import Schedule from './(components)/Schedule.svelte';
import Send from './(components)/Send.svelte';
import Target from './(components)/Target.svelte';
import MultiCodeContextless from './(components)/MultiCodeContextless.svelte';
import { Platform } from '$lib/utils/references';
const title = "Messaging" + TITLE_SUFFIX;
const title = 'Messaging' + TITLE_SUFFIX;
const description = DEFAULT_DESCRIPTION;
const ogImage = DEFAULT_HOST + "/images/open-graph/website.png";
const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
const codeTopic = [
{
language: "js",
language: 'client-web',
content: `import { Account, Messaging, ID } from "appwrite"
// Fetch target ID
@@ -29,10 +30,10 @@ await messaging.createSubscriber(
['news', 'sport'], // Topic ID
ID.unique(), // Subscription ID
targetId, // Target ID
)`,
)`
},
{
language: "dart",
language: 'client-flutter',
content: `import 'package:appwrite/appwrite.dart';
// Fetch target ID
@@ -46,10 +47,10 @@ await messaging.createSubscriber(
topicId: 'news',
subscriberId: ID.unique(),
targetId: targetId
);`,
);`
},
{
language: "kotlin",
language: 'client-android-kotlin',
content: `import io.appwrite.services.Account
import io.appwrite.services.Messaging
import io.appwrite.ID
@@ -65,10 +66,10 @@ messaging.createSubscriber(
topicId = "news",
subscriberId = ID.unique(),
targetId = targetId
)`,
)`
},
{
language: "swift",
language: 'client-apple',
content: `import Appwrite
// Fetch target ID
@@ -82,14 +83,14 @@ try await messaging.createSubscriber(
topicId: "news",
subscriberId: ID.unique(),
targetId: targetId
)`,
},
)`
}
];
const codeMessage = [
{
language: "js",
platform: "Node.js",
language: 'server-nodejs',
platform: 'Node.js',
content: `import { Messaging, ID } from "node-appwrite"
const messaging = Messaging(client);
@@ -98,24 +99,11 @@ await messaging.createPush(
'Breaking update', // Push title
'Hello, world!', // Push body
['news', 'sport'], // Topic IDs
);`,
);`
},
{
language: "ts",
platform: "Deno",
content: `import { Messaging, ID } from "https://deno.land/x/appwrite/mod.ts";
const messaging = new Messaging(client);
await messaging.createPush(
ID.unique(), // Message ID
'Breaking update', // Push title
'Hello, world!', // Push body
['news', 'sport'], // Topic IDs
);`,
},
{
language: "cs",
platform: ".NET",
language: 'cs',
platform: '.NET',
content: `using Appwrite.Services.Messaging;
using Appwrite.ID;
@@ -125,11 +113,11 @@ await messaging.createPush(
subject: "Breaking update",
content: "Hello, world!",
topics: ['news', 'sport'],
);`,
);`
},
{
language: "kotlin",
platform: "Kotlin",
language: 'kotlin',
platform: 'Kotlin',
content: `import io.appwrite.services.Messaging
import io.appwrite.ID
@@ -139,11 +127,11 @@ messaging.createPush(
subject = "Breaking update",
content = "Hello, world!",
topics: listOf('news'),
)`,
)`
},
{
language: "swift",
platform: "Swift",
language: 'swift',
platform: 'Swift',
content: `import Appwrite
let messaging = Messaging(client)
@@ -152,11 +140,11 @@ try await messaging.createPush(
subject: "Breaking update",
content: "Hello, world!",
topics: ["news", "sport"]
)`,
)`
},
{
language: "php",
platform: "PHP",
language: 'php',
platform: 'PHP',
content: `import 'package:appwrite/appwrite.dart';
final messaging = Messaging(client);
@@ -165,11 +153,11 @@ await messaging.createPush(
subject: "Breaking update",
content: "Hello, world!",
topics: ["news", "sport"],
);`,
);`
},
{
language: "dart",
platform: "Dart",
language: 'dart',
platform: 'Dart',
content: `<?php
use Appwrite\Services\Messaging;
@@ -181,11 +169,11 @@ $messaging->createPush(
subject: 'Breaking update',
content: 'Hello, world!',
topics: ['news', 'sport']
);`,
);`
},
{
language: "python",
platform: "Python",
language: 'python',
platform: 'Python',
content: `from appwrite.services.messaging import Messaging
from appwrite.id import ID
@@ -195,11 +183,11 @@ messaging.create_email(
subject = "Breaking update",
content = "Hello, world!",
topics = ["news", "sport"]
)`,
)`
},
{
language: "dart",
platform: "Dart",
language: 'dart',
platform: 'Dart',
content: `<?php
use Appwrite\Services\Messaging;
@@ -211,11 +199,11 @@ $messaging->createPush(
subject: 'Breaking update',
content: 'Hello, world!',
topics: ['news', 'sport']
);`,
);`
},
{
language: "ruby",
platform: "Ruby",
language: 'ruby',
platform: 'Ruby',
content: `require 'appwrite'
include Appwrite
@@ -226,8 +214,8 @@ messaging.create_email(
subject: 'Breaking update',
content: 'Hello, world!',
topics: ['news', 'sport']
)`,
},
)`
}
];
</script>
@@ -249,7 +237,7 @@ messaging.create_email(
</svelte:head>
<Main>
<div class="web-big-padding-section overflow-hidden">
<div class="web-big-padding-section u-overflow-hidden">
<div class="hero">
<img
src="/images/products/messaging/blur-left.png"
@@ -275,31 +263,19 @@ messaging.create_email(
Open source messaging service for developers
</h1>
<p class="web-description u-margin-block-start-20">
Set up messaging within minutes and send push notifications, emails,
and SMS directly to your users.
Set up messaging within minutes and send push notifications, emails, and SMS
directly to your users.
</p>
<div
class="u-items-center u-margin-block-start-32 hero-buttons flex gap-2"
>
<a
class="web-button"
href="https://cloud.appwrite.io"
target="_blank">Get started</a
>
<a
class="web-button is-secondary"
href="https://appwrite.io/docs/products/messaging"
target="_blank">Documentation</a
<div class="u-flex u-items-center u-gap-8 u-margin-block-start-32 hero-buttons">
<a class="web-button" href="https://cloud.appwrite.io">Get started</a>
<a class="web-button is-secondary" href="/docs/products/messaging"
>Documentation</a
>
</div>
</div>
<div class="phone-wrapper">
<img
class="phone"
src="/images/products/messaging/phone.png"
alt=""
/>
<img class="phone" src="/images/products/messaging/phone.png" alt="" />
</div>
</div>
</div>
@@ -312,12 +288,9 @@ messaging.create_email(
</div>
<div
class="web-big-padding-section-level-1 web-white-section light web-u-padding-block-end-0 relative"
>
<div
class="web-big-padding-section-level-2"
style="margin-block-end: 160px"
class="web-big-padding-section-level-1 u-position-relative web-white-section theme-light web-u-padding-block-end-0"
>
<div class="web-big-padding-section-level-2" style="margin-block-end: 160px">
<div class="web-container">
<section class="web-hero is-align-start">
<span class="web-badges web-eyebrow">capabilities_</span>
@@ -325,7 +298,7 @@ messaging.create_email(
All of your messages in one place
</h2>
</section>
<div class="web-u-margin-block-start-80 overflow-hidden">
<div class="u-overflow-hidden web-u-margin-block-start-80">
<ul class="web-info-boxes is-desktop-max-out-3 web-sub-body-500">
<li class="web-info-boxes-item">
<img
@@ -339,13 +312,11 @@ messaging.create_email(
Effortlessly send push notifications for seamless instant
communication.
</p>
<ul class="u-margin-block-start-16 flex flex-wrap gap-2">
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<li>
<a
class="web-interactive-tag"
href="/docs/products/messaging/fcm"
target="_blank"
rel="noopener noreferrer"
>
<span class="web-icon-firebase" aria-hidden="true" />
<span class="text">FCM</span>
@@ -355,8 +326,6 @@ messaging.create_email(
<a
class="web-interactive-tag"
href="/docs/products/messaging/apns"
target="_blank"
rel="noopener noreferrer"
>
<span class="web-icon-apple" aria-hidden="true" />
<span class="text">APNS</span>
@@ -376,13 +345,11 @@ messaging.create_email(
Easily send emails for smooth communication and information
sharing.
</p>
<ul class="u-margin-block-start-16 flex flex-wrap gap-2">
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<li>
<a
class="web-interactive-tag"
href="/docs/products/messaging/mailgun"
target="_blank"
rel="noopener noreferrer"
>
<span class="web-icon-mailgun" aria-hidden="true" />
<span class="text">Mailgun</span>
@@ -392,8 +359,6 @@ messaging.create_email(
<a
class="web-interactive-tag"
href="/docs/products/messaging/sendgrid"
target="_blank"
rel="noopener noreferrer"
>
<span class="web-icon-sendgrid" aria-hidden="true" />
<span class="text">SendGrid</span>
@@ -412,13 +377,11 @@ messaging.create_email(
<p class="web-info-boxes-content">
Send SMS for quick updates beyond your app's environment.
</p>
<ul class="u-margin-block-start-16 flex flex-wrap gap-2">
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<li>
<a
class="web-interactive-tag"
href="/docs/products/messaging/twilio"
target="_blank"
rel="noopener noreferrer"
>
<span class="icon-twilio" aria-hidden="true" />
<span class="text">Twilio</span>
@@ -428,8 +391,6 @@ messaging.create_email(
<a
class="web-interactive-tag"
href="/docs/products/messaging/vonage"
target="_blank"
rel="noopener noreferrer"
>
<span class="icon-vonage" aria-hidden="true" />
<span class="text">Vonage</span>
@@ -456,14 +417,9 @@ messaging.create_email(
<p class="web-info-boxes-content">
Send realtime alerts to your users within your application.
</p>
<ul class="u-margin-block-start-16 flex flex-wrap gap-2">
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<li>
<a
class="web-interactive-tag"
href="/docs"
target="_blank"
rel="noopener noreferrer"
>
<a class="web-interactive-tag" href="/docs">
<span
class="web-icon-appwrite u-small web-u-margin-inline-end-4"
aria-hidden="true"
@@ -487,7 +443,7 @@ messaging.create_email(
<p class="web-info-boxes-content">
Connect chat apps such as Slack, Discord, and WhatsApp.
</p>
<ul class="u-margin-block-start-16 flex flex-wrap gap-2">
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<li>
<span class="web-interactive-tag" data-readonly>
<span class="icon-slack" aria-hidden="true" />
@@ -512,15 +468,15 @@ messaging.create_email(
</div>
</div>
</div>
<!-- <div class="web-big-padding-section-level-2 relative z-1 light">
<div class="web-container relative">
<!-- <div class="web-big-padding-section-level-2 u-position-relative u-z-index-1 theme-light">
<div class="web-container u-position-relative">
<img
class="absolute z-1 is-not-mobile"
class="u-position-absolute u-z-index-1 is-not-mobile"
style="width:1500px; height:auto; max-block-size:none; max-inline-size:none; inset-block-end:-27rem; rotate:145deg; inset-inline-start:-42rem;"
src="/images/messaging/stripes.png"
alt="stripes"
/>
<div class="grid grid-cols-2relative z-1">
<div class="grid-1-1 u-position-relative u-z-index-1">
<section class="web-hero is-align-start">
<span class="web-badges web-eyebrow">PERFORMANCE_</span>
<h2 class="web-display u-max-width-600 web-u-color-text-primary">
@@ -555,7 +511,7 @@ messaging.create_email(
</div>
<div
class="relative z-1"
class="u-position-relative u-z-index-1"
style="background-color:hsl(var(--web-color-greyscale-900)); padding-block-start: 40px"
>
<div class="web-big-padding-section-level-2">
@@ -567,12 +523,10 @@ messaging.create_email(
</h2>
</div>
<div
class="grid-cols-2-opt-2 web-gap-24 web-u-margin-block-start-64 code-snippets grid"
class="web-grid-1-1-opt-2 web-u-gap-64 web-u-margin-block-start-64 code-snippets"
>
<div class="u-flex-vertical u-min-width-0 gap-2">
<h3 class="web-label web-u-color-text-primary">
Subscribe to a topic
</h3>
<div class="u-flex-vertical u-gap-8 u-min-width-0">
<h3 class="web-label web-u-color-text-primary">Subscribe to a topic</h3>
<p class="web-description">
Subscribe to receive all messages related to a topic.
</p>
@@ -581,16 +535,22 @@ messaging.create_email(
class="u-margin-block-start-16 u-min-width-0"
style="margin-block-end: 94px"
>
<MultiCodeContextless data={codeTopic} height={450} />
<MultiCodeContextless
data={codeTopic}
selected={Platform.ClientWeb}
height={450}
/>
</div>
</div>
<div class="u-flex-vertical u-min-width-0 gap-2">
<div class="u-flex-vertical u-gap-8 u-min-width-0">
<h3 class="web-label web-u-color-text-primary">Send a message</h3>
<p class="web-description">
Send a message to all targets on a topic.
</p>
<p class="web-description">Send a message to all targets on a topic.</p>
<div class="u-margin-block-start-16 u-min-width-0">
<MultiCodeContextless data={codeMessage} height={450} />
<MultiCodeContextless
data={codeMessage}
selected={Platform.ServerNodeJs}
height={450}
/>
</div>
</div>
</div>
@@ -606,7 +566,7 @@ messaging.create_email(
Keep exploring our products
</h4>
<ul
class="u-margin-block-start-32 grid gap-8"
class="u-grid u-gap-32 u-margin-block-start-32"
style="grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr))"
>
<li class="web-u-flex-basis-378">
@@ -614,22 +574,18 @@ messaging.create_email(
class="web-card is-normal"
href="/docs/products/auth"
style="background: rgba(255, 255, 255, 0.04);"
target="_blank"
rel="noopener noreferrer"
>
<div
class="u-flex-vertical web-u-padding-block-end-8 gap-2 ps-2 pe-2"
class="u-flex-vertical u-gap-8 web-u-padding-inline-8 web-u-padding-block-end-8"
>
<div class="u-cross-center flex gap-2">
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/auth.png"
alt="auth"
width="32"
height="32"
/>
<h4 class="web-main-body-400 web-u-color-text-primary">
Auth
</h4>
<h4 class="web-main-body-400 web-u-color-text-primary">Auth</h4>
<span
class="web-icon-arrow-right u-margin-inline-start-auto"
aria-hidden="true"
@@ -645,14 +601,12 @@ messaging.create_email(
<a
class="web-card is-normal"
href="/docs/products/functions"
target="_blank"
rel="noopener noreferrer"
style="background: rgba(255, 255, 255, 0.04);"
>
<div
class="u-flex-vertical web-u-padding-block-end-8 gap-2 ps-2 pe-2"
class="u-flex-vertical u-gap-8 web-u-padding-inline-8 web-u-padding-block-end-8"
>
<div class="u-cross-center flex gap-2">
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/functions.png"
alt="functions"
@@ -678,14 +632,12 @@ messaging.create_email(
<a
class="web-card is-normal"
href="/docs/products/databases"
target="_blank"
rel="noopener noreferrer"
style="background: rgba(255, 255, 255, 0.04);"
>
<div
class="u-flex-vertical web-u-padding-block-end-8 gap-2 ps-2 pe-2"
class="u-flex-vertical u-gap-8 web-u-padding-inline-8 web-u-padding-block-end-8"
>
<div class="u-cross-center flex gap-2">
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/databases.png"
alt=""
@@ -710,14 +662,12 @@ messaging.create_email(
<a
class="web-card is-normal"
href="/docs/products/storage"
target="_blank"
rel="noopener noreferrer"
style="background: rgba(255, 255, 255, 0.04);"
>
<div
class="u-flex-vertical web-u-padding-block-end-8 gap-2 ps-2 pe-2"
class="u-flex-vertical u-gap-8 web-u-padding-inline-8 web-u-padding-block-end-8"
>
<div class="u-cross-center flex gap-2">
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/storage.png"
alt="storage"
@@ -733,8 +683,7 @@ messaging.create_email(
/>
</div>
<p class="web-sub-body-400">
Manage your files' project, using convenient APIs and
utilities.
Manage your files' project, using convenient APIs and utilities.
</p>
</div>
</a>
@@ -743,14 +692,12 @@ messaging.create_email(
<a
class="web-card is-normal"
href="/docs/apis/realtime"
target="_blank"
rel="noopener noreferrer"
style="background: rgba(255, 255, 255, 0.04);"
>
<div
class="u-flex-vertical web-u-padding-block-end-8 gap-2 ps-2 pe-2"
class="u-flex-vertical u-gap-8 web-u-padding-inline-8 web-u-padding-block-end-8"
>
<div class="u-cross-center flex gap-2">
<div class="u-flex u-cross-center u-gap-8">
<img
src="/images/icons/illustrated/dark/realtime.png"
alt="realtime"
@@ -774,9 +721,7 @@ messaging.create_email(
</ul>
</div>
</section>
<div
class="web-big-padding-section-level-2 is-margin-replace-padding relative"
>
<div class="web-big-padding-section-level-2 is-margin-replace-padding u-position-relative">
<div class="web-container">
<PreFooter />
<FooterNav />
@@ -848,7 +793,7 @@ messaging.create_email(
}
}
[class^="blur-"] {
[class^='blur-'] {
max-inline-size: unset;
max-block-size: unset;
pointer-events: none;
@@ -897,7 +842,7 @@ messaging.create_email(
.code-snippets {
position: relative;
&:before {
content: "";
content: '';
position: absolute;
inset: 0;
inset-inline-start: 50%;
@@ -917,6 +862,10 @@ messaging.create_email(
pointer-events: none;
}
.web-tag {
--p-tag-bg-color: var(--web-color-greyscale-100);
}
@media (min-width: 1024px) {
.hero {
padding-block-start: 0;

View File

@@ -1,10 +1,11 @@
---
layout: policy
title: Terms and Conditions
description: Review our Terms of Service to understand the rules and guidelines for using our open-source backend-as-a-service platform.
---
These Terms and Conditions ("Terms," "Terms and Conditions") govern your relationship with [https://appwrite.io](https://appwrite.io) website (the "Service") operated by Appwrite ("us," "we," or "our").
These Terms and Conditions ("Terms," "Terms and Conditions") govern your relationship with [Appwrite (https://appwrite.io)](https://appwrite.io) website (the "Service") operated by Appwrite ("us," "we," or "our").
Please read these Terms and Conditions carefully before using the Service.

View File

@@ -72,12 +72,14 @@
--p-input-bg-color: var(--p-input-bg-color-hover);
--p-input-border-color: var(--p-input-border-color-hover);
}
&:is(:focus) {
&:is(:focus),
&:has(:focus) {
--p-input-bg-color: var(--p-input-bg-color-focus);
--p-input-border-color: var(--p-input-border-color-focus);
box-shadow: 0 0 0 pxToRem(4) hsl(var(--p-input-focus-box-shadow-color));
}
&:is(:active) {
&:is(:active),
&:has(:active){
--p-input-bg-color: var(--p-input-bg-color-active);
--p-input-border-color: var(--p-input-border-color-active);
box-shadow: 0 0 0 pxToRem(4) hsl(var(--p-input-focus-box-shadow-color));
@@ -89,6 +91,10 @@
--p-input-border-color: var(--p-input-border-color-disabled);
opacity: 0.4;
}
input:focus {
box-shadow:none;
inline-size:100%;
}
&-search-wrapper {
position:relative; min-inline-size:pxToRem(350);

View File

@@ -127,7 +127,6 @@
&.is-reset-input-inside {
input { all:unset; display:block; inline-size:100%; text-align:left; }
}
}
textarea.#{$p}-input-text {
@@ -136,6 +135,8 @@ textarea.#{$p}-input-text {
block-size: pxToRem(154);
}
select.#{$p}-input-text { color:hsl(var(--color-neutral-40)); }
.#{$p}-subscribe-input {
padding: pxToRem(4); padding-inline-start:pxToRem(16);
::placeholder { color:hsl(var(--web-color-primary)); opacity:0.64; }

View File

@@ -0,0 +1,54 @@
@use '../abstract' as *;
.#{$p}-carousel {
position:relative;
@media (min-width: 768px) {
&::before {
content:""; display:block;
position:absolute; z-index:1; inset:0; inset-inline:pxToRem(0);
background: linear-gradient(90deg, rgba(23, 23, 26, 1) 0%, rgba(23, 23, 26, 0.88) 9.65%, rgba(23, 23, 26, 0) 25%, rgba(23, 23, 26, 0) 50%, rgba(23, 23, 26, 0) 75%, rgba(23, 23, 26, 0.88) 89.28%, rgba(23, 23, 26, 1) 100%);
pointer-events: none;
}
}
&-item {
img {
display:block; inline-size:100%; border:solid pxToRem(2) hsl(var(--web-color-smooth));
border-radius:var(--border-radius-medium); transition:var(--transition);
}
}
&-button {
display:flex; justify-content:center; align-items:center; inline-size:pxToRem(40); block-size:pxToRem(40);
border-radius:var(--border-radius-circular); flex-shrink:0;
background:hsl(var(--web-color-white) / 0.15); color:hsl(var(--web-color-white));
&-start { position:absolute; z-index:2; inset-block-start:50%; inset-inline-start:calc( calc(100% - #{pxToRem(584)}) / 2 - #{pxToRem(100)} ); }
&-end { position:absolute; z-index:2; inset-block-start:50%; inset-inline-end:calc( calc(100% - #{pxToRem(584)}) / 2 - #{pxToRem(100)} ); }
}
&-bullets {
inline-size:fit-content; margin-inline:auto;
&-list { display:flex; margin-block-start:pxToRem(20); }
&-button {
display:grid; place-content:center; inline-size:pxToRem(16); block-size:pxToRem(16); border-radius:var(--border-radius-circular);
&::before {
content:""; display:block; inline-size:pxToRem(6); block-size:pxToRem(6); border-radius:var(--border-radius-circular);
background-color:hsl(var(--web-color-white)); opacity:0.4; transition:var(--transition);
}
&.is-selected::before { opacity:1; }
}
}
@media #{$break1} {
&-button { display:none; }
}
}
.#{$p}-integrations-top-section {
display:flex; flex-direction:column; justify-content:center;
@media (max-width:767.9px) { min-block-size: pxToRem(370); padding-block:pxToRem(40); }
@media (min-width:768px) and (max-width:1023.9px) { min-block-size: pxToRem(495); padding-block:pxToRem(48); }
@media #{$break2open} {
min-block-size:pxToRem(548); padding-block:pxToRem(48);
}
}

View File

@@ -25,6 +25,7 @@
@forward "timeline-content";
@forward "investor-cards";
@forward "chat";
@forward "carousel";
/*article content */
@forward "article";

View File

@@ -4,7 +4,10 @@
display:grid; column-gap:pxToRem(16); grid-template-columns:auto 1fr;
font-size:pxToRem(18); line-height:pxToRem(24);
&-image { grid-row:span 2; display:block; inline-size:pxToRem(48); block-size:pxToRem(48); border-radius:50%; }
&-image {
grid-row:span 2; display:block; inline-size:pxToRem(48); block-size:pxToRem(48); border-radius:50%;
&.is-32px { inline-size:pxToRem(32); block-size:pxToRem(32); }
}
&-name { color:hsl(var(--web-color-greyscale-700)); }
&-username { color:hsl(var(--web-color-greyscale-600)); }
}

View File

@@ -9,3 +9,4 @@
@forward "feature-article";
@forward "grid-articles";
@forward "main-article";
@forward "overlay-item";

View File

@@ -0,0 +1,19 @@
@use '../abstract' as *;
.#{$p}-overlay-item {
position: relative;
display: block;
border-radius: var(--border-radius-medium);
border: pxToRem(1) solid hsl(var(--smooth));
overflow:hidden;
img { border-radius:inherit; }
&::before {
position:absolute; inset:0;
content:""; display:block;
border-radius:inherit;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.00) 0%, rgba(0, 0, 0, 0.00) 50%, rgba(0, 0, 0, 0.64) 74.79%, #000 100%), rgba(255, 255, 255, 0.04);
}
.web-user-box {
position:absolute; inset-inline-start:pxToRem(16); inset-block-end:pxToRem(16);
&-image { inline-size:pxToRem(40); block-size:pxToRem(40); margin-block:auto; }
}
}

View File

@@ -0,0 +1,9 @@
@use '../abstract' as *;
.#{$p}-feature-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: pxToRem(32);
@media (max-width:767.9px) { grid-template-columns: 1fr; }
@media (min-width:768px) { grid-template-columns: repeat(2, 1fr); }
}

View File

@@ -11,3 +11,4 @@
@forward "grid-side-nav";
@forward "grid-two-side-navs";
@forward "grid-huge-navs";
@forward "feature-grid";

View File

@@ -162,11 +162,13 @@
.#{$p}-u-flex-basis-400 { flex-basis:pxToRem(400); }
.#{$p}-u-translate-x-negative { transform:translateX(-100%); }
.#{$p}-gap-2 { gap:pxToRem(6); }
.#{$p}-gap-5 { gap:pxToRem(20)!important; }
.#{$p}-gap-5-mobile { @media #{$break1} { gap:pxToRem(20)!important; } }
.#{$p}-gap-8 { gap:pxToRem(32)!important; }
.#{$p}-gap-24 { gap:pxToRem(64)!important; }
.#{$p}-u-gap-6 { gap:pxToRem(6); }
.#{$p}-u-gap-20 { gap:pxToRem(20)!important; }
.#{$p}-u-gap-20-mobile { @media #{$break1} { gap:pxToRem(20)!important; } }
.#{$p}-u-gap-40-mobile { @media #{$break1} { gap:pxToRem(40)!important; } }
.#{$p}-u-gap-60-not-mobile { @media #{$break2open} { gap:pxToRem(60)!important; } }
.#{$p}-u-gap-32 { gap:pxToRem(32)!important; }
.#{$p}-u-gap-64 { gap:pxToRem(64)!important; }
.#{$p}-u-gap-80 { gap:pxToRem(80); }
.#{$p}-gap-24 { gap:pxToRem(96); }
.#{$p}-u-row-gap-24 { row-gap: pxToRem(24)!important; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 KiB

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