Merge branch 'main' of https://github.com/appwrite/website into feat-eldads-update5

This commit is contained in:
Torsten Dittmann
2023-09-26 19:45:47 +02:00
140 changed files with 2774 additions and 1414 deletions

23
.github/workflows/index.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Search Index
on:
push:
branches:
- main
jobs:
indexing:
runs-on: ubuntu-latest
name: Indexing
steps:
- uses: actions/checkout@v4
with:
repository: 'meilisearch/scrapix'
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '20.x'
- run: yarn
- run: yarn start -c "$SCRAPIX_CONFIG"
env:
SCRAPIX_CONFIG: ${{ secrets.SCRAPIX_CONFIG }}

25
.idea/workspace.xml generated Normal file
View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="b9b3f992-a7ab-4f15-8768-3d0a4a05287d" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ComposerSettings">
<execution />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"dart.analysis.tool.window.visible": "false",
"node.js.selected.package.tslint": "(autodetect)"
}
}]]></component>
<component name="TaskManager">
<servers />
</component>
</project>

28
LICENSE Normal file
View File

@@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2023, Appwrite
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,43 @@
# Website 🖥️
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord)
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite)
[![appwrite.io](https://img.shields.io/badge/appwrite-.io-f02e65?style=flat-square)](https://appwrite.io)
![Cover banner](https://github.com/appwrite/website/assets/31401437/0852817d-b482-4e06-a002-ee84b2a7052c)
The Appwrite Website repo features the main Appwrite website, including our [homepage](https://appwrite.io), [docs](https://appwrite.io/docs), and upcoming blog.
The Appwrite Website has been built with the following frameworks:
- [Svelte](https://svelte.dev/)
- [SvelteKit](https://kit.svelte.dev/)
## Development
*If this is your first time setting up the repository, please run `pnpm install` inside the repo's directory.*
To get the repo up and running in your local environment, use the following command:
```bash
pnpm run dev
```
> If you don't have `pnpm` available on your system, you can install it from the [official pnpm Installation website](https://pnpm.io/installation)
## Contributing
All code contributions, including those of people with commit access, must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](./CONTRIBUTING.md).
## Security
For security issues, kindly email us at [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue on GitHub.
## Follow Us
Join our growing community around the world! See our official [Blog](https://medium.com/appwrite-io). Follow us on [Twitter](https://twitter.com/appwrite), [Facebook Page](https://www.facebook.com/appwrite.io), [Facebook Group](https://www.facebook.com/groups/appwrite.developers/), and [Dev Community](https://dev.to/appwrite) or join our live [Discord server](https://appwrite.io/discord) for more help, ideas, and discussions.
## License
This repository is available under the [BSD 3-Clause License](./LICENSE).

View File

@@ -19,6 +19,7 @@
"@melt-ui/pp": "^0.1.2", "@melt-ui/pp": "^0.1.2",
"@melt-ui/svelte": "^0.47.6", "@melt-ui/svelte": "^0.47.6",
"@playwright/test": "^1.37.1", "@playwright/test": "^1.37.1",
"@sveltejs/adapter-node": "^1.3.1",
"@sveltejs/adapter-static": "^2.0.3", "@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.24.1", "@sveltejs/kit": "^1.24.1",
"@types/markdown-it": "^13.0.1", "@types/markdown-it": "^13.0.1",
@@ -48,6 +49,7 @@
"@appwrite.io/pink-icons": "0.1.0-next.9", "@appwrite.io/pink-icons": "0.1.0-next.9",
"@appwrite.io/repo": "github:appwrite/appwrite", "@appwrite.io/repo": "github:appwrite/appwrite",
"@fontsource/inter": "^5.0.8", "@fontsource/inter": "^5.0.8",
"dotenv": "^16.3.1",
"highlight.js": "^11.8.0", "highlight.js": "^11.8.0",
"markdown-it": "^13.0.1", "markdown-it": "^13.0.1",
"motion": "^10.16.2" "motion": "^10.16.2"

156
pnpm-lock.yaml generated
View File

@@ -17,6 +17,9 @@ dependencies:
'@fontsource/inter': '@fontsource/inter':
specifier: ^5.0.8 specifier: ^5.0.8
version: 5.0.8 version: 5.0.8
dotenv:
specifier: ^16.3.1
version: 16.3.1
highlight.js: highlight.js:
specifier: ^11.8.0 specifier: ^11.8.0
version: 11.8.0 version: 11.8.0
@@ -37,6 +40,9 @@ devDependencies:
'@playwright/test': '@playwright/test':
specifier: ^1.37.1 specifier: ^1.37.1
version: 1.38.0 version: 1.38.0
'@sveltejs/adapter-node':
specifier: ^1.3.1
version: 1.3.1(@sveltejs/kit@1.25.0)
'@sveltejs/adapter-static': '@sveltejs/adapter-static':
specifier: ^2.0.3 specifier: ^2.0.3
version: 2.0.3(@sveltejs/kit@1.25.0) version: 2.0.3(@sveltejs/kit@1.25.0)
@@ -603,10 +609,86 @@ packages:
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
dev: true dev: true
/@rollup/plugin-commonjs@25.0.4(rollup@3.28.0):
resolution: {integrity: sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^2.68.0||^3.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
'@rollup/pluginutils': 5.0.4(rollup@3.28.0)
commondir: 1.0.1
estree-walker: 2.0.2
glob: 8.1.0
is-reference: 1.2.1
magic-string: 0.27.0
rollup: 3.28.0
dev: true
/@rollup/plugin-json@6.0.0(rollup@3.28.0):
resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
'@rollup/pluginutils': 5.0.4(rollup@3.28.0)
rollup: 3.28.0
dev: true
/@rollup/plugin-node-resolve@15.2.1(rollup@3.28.0):
resolution: {integrity: sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^2.78.0||^3.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
'@rollup/pluginutils': 5.0.4(rollup@3.28.0)
'@types/resolve': 1.20.2
deepmerge: 4.3.1
is-builtin-module: 3.2.1
is-module: 1.0.0
resolve: 1.22.6
rollup: 3.28.0
dev: true
/@rollup/pluginutils@5.0.4(rollup@3.28.0):
resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
'@types/estree': 1.0.1
estree-walker: 2.0.2
picomatch: 2.3.1
rollup: 3.28.0
dev: true
/@sinclair/typebox@0.27.8: /@sinclair/typebox@0.27.8:
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
dev: true dev: true
/@sveltejs/adapter-node@1.3.1(@sveltejs/kit@1.25.0):
resolution: {integrity: sha512-A0VgRQDCDPzdLNoiAbcOxGw4zT1Mc+n1LwT1OmO350R7WxrEqdMUChPPOd1iMfIDWlP4ie6E2d/WQf5es2d4Zw==}
peerDependencies:
'@sveltejs/kit': ^1.0.0
dependencies:
'@rollup/plugin-commonjs': 25.0.4(rollup@3.28.0)
'@rollup/plugin-json': 6.0.0(rollup@3.28.0)
'@rollup/plugin-node-resolve': 15.2.1(rollup@3.28.0)
'@sveltejs/kit': 1.25.0(svelte@4.2.0)(vite@4.4.9)
rollup: 3.28.0
dev: true
/@sveltejs/adapter-static@2.0.3(@sveltejs/kit@1.25.0): /@sveltejs/adapter-static@2.0.3(@sveltejs/kit@1.25.0):
resolution: {integrity: sha512-VUqTfXsxYGugCpMqQv1U0LIdbR3S5nBkMMDmpjGVJyM6Q2jHVMFtdWJCkeHMySc6mZxJ+0eZK3T7IgmUCDrcUQ==} resolution: {integrity: sha512-VUqTfXsxYGugCpMqQv1U0LIdbR3S5nBkMMDmpjGVJyM6Q2jHVMFtdWJCkeHMySc6mZxJ+0eZK3T7IgmUCDrcUQ==}
peerDependencies: peerDependencies:
@@ -766,6 +848,10 @@ packages:
resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==}
dev: true dev: true
/@types/resolve@1.20.2:
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
dev: true
/@types/semver@7.5.0: /@types/semver@7.5.0:
resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
dev: true dev: true
@@ -1231,6 +1317,11 @@ packages:
readable-stream: 3.6.2 readable-stream: 3.6.2
dev: true dev: true
/builtin-modules@3.3.0:
resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
engines: {node: '>=6'}
dev: true
/busboy@1.6.0: /busboy@1.6.0:
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
engines: {node: '>=10.16.0'} engines: {node: '>=10.16.0'}
@@ -1428,6 +1519,10 @@ packages:
engines: {node: ^12.20.0 || >=14} engines: {node: ^12.20.0 || >=14}
dev: true dev: true
/commondir@1.0.1:
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
dev: true
/component-emitter@1.3.0: /component-emitter@1.3.0:
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
dev: true dev: true
@@ -1671,6 +1766,11 @@ packages:
domhandler: 5.0.3 domhandler: 5.0.3
dev: true dev: true
/dotenv@16.3.1:
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
engines: {node: '>=12'}
dev: false
/eastasianwidth@0.2.0: /eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: true dev: true
@@ -1913,6 +2013,10 @@ packages:
engines: {node: '>=4.0'} engines: {node: '>=4.0'}
dev: true dev: true
/estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
dev: true
/estree-walker@3.0.3: /estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
dependencies: dependencies:
@@ -2118,6 +2222,10 @@ packages:
dev: true dev: true
optional: true optional: true
/function-bind@1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
/gauge@4.0.4: /gauge@4.0.4:
resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@@ -2280,6 +2388,13 @@ packages:
kind-of: 4.0.0 kind-of: 4.0.0
dev: true dev: true
/has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
dependencies:
function-bind: 1.1.1
dev: true
/hey-listen@1.0.8: /hey-listen@1.0.8:
resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
dev: false dev: false
@@ -2418,6 +2533,19 @@ packages:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
dev: true dev: true
/is-builtin-module@3.2.1:
resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
engines: {node: '>=6'}
dependencies:
builtin-modules: 3.3.0
dev: true
/is-core-module@2.13.0:
resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
dependencies:
has: 1.0.3
dev: true
/is-data-descriptor@0.1.4: /is-data-descriptor@0.1.4:
resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -2483,6 +2611,10 @@ packages:
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
dev: true dev: true
/is-module@1.0.0:
resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
dev: true
/is-number@3.0.0: /is-number@3.0.0:
resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -2512,6 +2644,12 @@ packages:
isobject: 3.0.1 isobject: 3.0.1
dev: true dev: true
/is-reference@1.2.1:
resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
dependencies:
'@types/estree': 1.0.1
dev: true
/is-reference@3.0.1: /is-reference@3.0.1:
resolution: {integrity: sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==} resolution: {integrity: sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==}
dependencies: dependencies:
@@ -3235,6 +3373,10 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/path-scurry@1.10.1: /path-scurry@1.10.1:
resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
@@ -3502,6 +3644,15 @@ packages:
deprecated: https://github.com/lydell/resolve-url#deprecated deprecated: https://github.com/lydell/resolve-url#deprecated
dev: true dev: true
/resolve@1.22.6:
resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==}
hasBin: true
dependencies:
is-core-module: 2.13.0
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
dev: true
/ret@0.1.15: /ret@0.1.15:
resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@@ -3876,6 +4027,11 @@ packages:
has-flag: 4.0.0 has-flag: 4.0.0
dev: true dev: true
/supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
dev: true
/svelte-check@3.5.1(postcss@8.4.27)(sass@1.66.1)(svelte@4.2.0): /svelte-check@3.5.1(postcss@8.4.27)(sass@1.66.1)(svelte@4.2.0):
resolution: {integrity: sha512-+Zb4iHxAhdUtcUg/WJPRjlS1RJalIsWAe9Mz6G1zyznSs7dDkT7VUBdXc3q7Iwg49O/VrZgyJRvOJkjuBfKjFA==} resolution: {integrity: sha512-+Zb4iHxAhdUtcUg/WJPRjlS1RJalIsWAe9Mz6G1zyznSs7dDkT7VUBdXc3q7Iwg49O/VrZgyJRvOJkjuBfKjFA==}
hasBin: true hasBin: true

View File

@@ -1,3 +1,3 @@
<svg width="1200" height="1227" viewBox="0 0 1200 1227" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z" fill="white"/> <path d="M24.2089 3.20001H28.5517L19.0639 14.0439L30.2255 28.8H21.4861L14.641 19.8505L6.80875 28.8H2.46331L12.6114 17.2012L1.90405 3.20001H10.8654L17.0527 11.3802L24.2089 3.20001ZM22.6847 26.2006H25.0911L9.5578 5.66286H6.97548L22.6847 26.2006Z" fill="black"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 430 B

After

Width:  |  Height:  |  Size: 363 B

View File

@@ -1,6 +1,4 @@
<script lang="ts"> <script lang="ts">
import { toScale, type Scale } from '$lib/utils/toScale';
import { spring, type AnimationListOptions, type SpringOptions } from 'motion'; import { spring, type AnimationListOptions, type SpringOptions } from 'motion';
import { animation, createScrollHandler, scroll, type Animation } from '.'; import { animation, createScrollHandler, scroll, type Animation } from '.';
@@ -71,13 +69,10 @@
} }
]; ];
const animScale: Scale = [0, animations.length - 1];
const percentScale: Scale = [0.1, 0.9];
const scrollHandler = createScrollHandler( const scrollHandler = createScrollHandler(
animations.map(({ mobile, desktop }, i) => { animations.map(({ mobile, desktop }, i) => {
return { return {
percentage: toScale(i, animScale, percentScale), percentage: 0.1,
whenAfter() { whenAfter() {
const { main, reversed } = isMobile() ? mobile : desktop; const { main, reversed } = isMobile() ? mobile : desktop;
@@ -109,14 +104,10 @@
> >
<div class="sticky-wrapper"> <div class="sticky-wrapper">
<h3 class="aw-display aw-u-color-text-primary">Powered by Open Source</h3> <h3 class="aw-display aw-u-color-text-primary">Powered by Open Source</h3>
<p class="aw-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin in ultrices lacus. Duis
pellentesque quis purus.
</p>
<div class="cards-wrapper"> <div class="cards-wrapper">
<a <a
href="https://discord.com/invite/GSeTUeA" href="/discord"
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card" class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card"
id="oss-discord" id="oss-discord"
> >
@@ -148,7 +139,7 @@
<div class="aw-title u-margin-block-start-auto">125k+ Twitter Followers</div> <div class="aw-title u-margin-block-start-auto">125k+ Twitter Followers</div>
</a> </a>
<a class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card" id="oss-youtube"> <a href="https://www.youtube.com/@Appwrite" class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical oss-card" id="oss-youtube">
<div class="u-flex-vertical u-main-space-between u-gap-32"> <div class="u-flex-vertical u-main-space-between u-gap-32">
<span class="aw-icon-youtube aw-u-font-size-40" aria-hidden="true" aria-label="YouTube" /> <span class="aw-icon-youtube aw-u-font-size-40" aria-hidden="true" aria-label="YouTube" />
</div> </div>
@@ -171,7 +162,7 @@
<style lang="scss"> <style lang="scss">
#open-source { #open-source {
height: 3500px; height: 1500px;
position: relative; position: relative;
} }
@@ -203,10 +194,6 @@
inset: 0; inset: 0;
} }
p {
max-width: 48.875rem;
}
.cards-wrapper { .cards-wrapper {
position: relative; position: relative;
height: 22.5rem; height: 22.5rem;

View File

@@ -131,7 +131,7 @@
remaning: Infinity remaning: Infinity
}; };
const animScale: Scale = [0.1, 1]; const animScale: Scale = [0.075, 1];
const productsScales = products.map((_, idx) => { const productsScales = products.map((_, idx) => {
const diff = animScale[1] - animScale[0]; const diff = animScale[1] - animScale[0];
const step = diff / products.length; const step = diff / products.length;
@@ -193,17 +193,15 @@
> >
<div class="sticky-wrapper"> <div class="sticky-wrapper">
<!-- <div class="debug"> <!-- <div class="debug">
<pre>{JSON.stringify({ active })}</pre> <pre>{scrollInfo.percentage}</pre>
<pre>{JSON.stringify({ scrollInfo })}</pre>
</div> --> </div> -->
{#if scrollInfo.percentage < 0.075}
{#if scrollInfo.percentage < 0.1}
<div <div
class="main-text" class="main-text"
out:fly={{ duration: 250, y: -300 }} out:fly={{ duration: 250, y: -300 }}
in:fly={{ duration: 250, delay: 250, y: -300 }} in:fly={{ duration: 250, delay: 250, y: -300 }}
> >
{#if scrollInfo.percentage > 0} {#if scrollInfo.percentage > -0.1}
<span class="aw-badges aw-eyebrow" transition:slide={{ axis: 'x' }}>Products_</span> <span class="aw-badges aw-eyebrow" transition:slide={{ axis: 'x' }}>Products_</span>
<h2 class="aw-display" transition:fly={{ y: 16, delay: 250 }}> <h2 class="aw-display" transition:fly={{ y: 16, delay: 250 }}>
@@ -225,7 +223,7 @@
class="products" class="products"
out:fly={{ duration: 250, y: 300 }} out:fly={{ duration: 250, y: 300 }}
in:fly={{ duration: 500, delay: 250, y: 300 }} in:fly={{ duration: 500, delay: 250, y: 300 }}
data-active={scrollInfo.percentage > 0.1 ? '' : undefined} data-active={scrollInfo.percentage > 0.075 ? '' : undefined}
> >
<div class="text" id="pd-{$elId}"> <div class="text" id="pd-{$elId}">
<ScrollIndicator percentage={toScale(scrollInfo.percentage, animScale, [0, 1])} /> <ScrollIndicator percentage={toScale(scrollInfo.percentage, animScale, [0, 1])} />
@@ -336,9 +334,8 @@
<style lang="scss"> <style lang="scss">
#products { #products {
min-height: 500vh; min-height: 500vh;
height: 6000px; height: 5000px;
position: relative; position: relative;
padding-block-end: 20rem;
--debug-bg: transparent; --debug-bg: transparent;
@@ -351,12 +348,6 @@
} }
} }
// .debug {
// position: absolute;
// top: 8rem;
// left: 0;
// }
.sticky-wrapper { .sticky-wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -367,8 +358,7 @@
position: sticky; position: sticky;
top: 0; top: 0;
min-height: 58rem; // min-height: 58rem;
height: 100vh;
overflow: hidden; overflow: hidden;
padding-inline: 1.25rem; padding-inline: 1.25rem;
@@ -443,15 +433,12 @@
padding-block-start: 1.5rem; padding-block-start: 1.5rem;
} }
&:not(:last-child)[data-active] {
padding-block-end: 4.25rem;
}
transition: 100ms ease; transition: 100ms ease;
&[data-active] { &[data-active] {
h3 { h3 {
color: hsl(var(--aw-color-primary)); color: hsl(var(--aw-color-primary));
margin-block-end: 0.75rem;
} }
} }
} }
@@ -468,7 +455,6 @@
h4 { h4 {
color: hsl(var(--aw-color-primary)); color: hsl(var(--aw-color-primary));
margin-block-start: 0.75rem;
} }
p { p {

View File

@@ -56,22 +56,22 @@ const execute = async () => {
const { update } = state.reset(); const { update } = state.reset();
await Promise.all([ await Promise.all([
safeAnimate(box, { x: 310, y: 32, opacity: 0 }, { duration: 0.5 })?.finished, safeAnimate(box, { x: 310, y: 140, opacity: 0 }, { duration: 0.5 })?.finished,
safeAnimate(code, { x: 200, y: 460, opacity: 0 }, { duration: 0.5 })?.finished, safeAnimate(code, { x: 200, y: 460, opacity: 0 }, { duration: 0.5 })?.finished,
safeAnimate(phone, { x: 0, y: 0 }, { duration: 0.5 })?.finished, safeAnimate(phone, { x: 0, y: 0 }, { duration: 0.5 })?.finished,
safeAnimate(controls, { x: 420, y: 0, opacity: 0 }, { duration: 0.5 })?.finished safeAnimate(controls, { x: 420, y: 0, opacity: 0 }, { duration: 0.5 })?.finished
]); ]);
// Start // Start
await safeAnimate(box, { y: [48, 32], opacity: 1 }, { duration: 0.25, delay: 1 })?.finished; await safeAnimate(box, { y: [48, 140], opacity: 1 }, { duration: 0.25, delay: 0.25 })?.finished;
await sleep(150); await sleep(50);
await write(emailToSet, (v) => update((p) => ({ ...p, email: v })), 300); await write(emailToSet, (v) => update((p) => ({ ...p, email: v })), 300);
await sleep(150); await sleep(50);
await write(passwordToSet, (v) => update((p) => ({ ...p, password: v })), 300); await write(passwordToSet, (v) => update((p) => ({ ...p, password: v })), 300);
await sleep(500); await sleep(50);
await safeAnimate( await safeAnimate(
code, code,
@@ -79,7 +79,7 @@ const execute = async () => {
{ duration: 0.25 } { duration: 0.25 }
)?.finished; )?.finished;
await sleep(500); await sleep(350);
update((p) => ({ ...p, submitted: true })); update((p) => ({ ...p, submitted: true }));

View File

@@ -37,10 +37,10 @@ const execute = async () => {
await Promise.all([ await Promise.all([
safeAnimate(phone, { x: 390, y: 0 }, { duration: 0.5 })?.finished, safeAnimate(phone, { x: 390, y: 0 }, { duration: 0.5 })?.finished,
safeAnimate(box, { x: 0, y: 32, opacity: 1 }, { duration: 0.5 })?.finished, safeAnimate(box, { x: 0, y: 32, opacity: 1 }, { duration: 0.5 })?.finished,
safeAnimate(code, { x: 80, y: 460, opacity: 1 }, { duration: 0.5 })?.finished safeAnimate(code, { x: 80, y: 320, opacity: 1 }, { duration: 0.5 })?.finished
]); ]);
await sleep(1000); await sleep(250);
update((p) => ({ update((p) => ({
...p, ...p,
@@ -53,14 +53,14 @@ const execute = async () => {
} }
] ]
})); }));
await sleep(500); await sleep(250);
update((p) => ({ update((p) => ({
...p, ...p,
tableSlice: p.tableSlice + 1 tableSlice: p.tableSlice + 1
})); }));
await sleep(500); await sleep(250);
update((p) => ({ update((p) => ({
...p, ...p,
@@ -74,7 +74,7 @@ const execute = async () => {
] ]
})); }));
await sleep(500); await sleep(250);
update((p) => ({ update((p) => ({
...p, ...p,

View File

@@ -21,17 +21,17 @@ const execute = async () => {
const { update } = state.reset(); const { update } = state.reset();
await Promise.all([ await Promise.all([
safeAnimate(phone, { x: 460, y: 0, width: '275px' }, { duration: 0.5 })?.finished, safeAnimate(phone, { x: 430, y: 0, width: '275px' }, { duration: 0.5 })?.finished,
safeAnimate(code, { x: 0, y: 200, opacity: 0 }, { duration: 0.5 })?.finished, safeAnimate(code, { x: 0, y: 200, opacity: 0 }, { duration: 0.5 })?.finished,
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished
]); ]);
await sleep(500); await sleep(250);
await safeAnimate(code, { zIndex: 0 }, { duration: 0 })?.finished; await safeAnimate(code, { zIndex: 0 }, { duration: 0 })?.finished;
await safeAnimate(code, { y: [200 - 16, 200], opacity: 1 }, { duration: 0.5 })?.finished; await safeAnimate(code, { y: [200 - 16, 200], opacity: 1 }, { duration: 0.5 })?.finished;
await sleep(500); await sleep(250);
update((p) => ({ update((p) => ({
...p, ...p,

View File

@@ -57,14 +57,14 @@ const execute = async () => {
] ]
})); }));
await sleep(1000); await sleep(250);
await Promise.all([ await Promise.all([
safeAnimate(overlay, { opacity: 1 }, { duration: 0.25 })?.finished, safeAnimate(overlay, { opacity: 1 }, { duration: 0.25 })?.finished,
safeAnimate(drawer, { y: [128, 0], opacity: 1 }, { duration: 0.5 })?.finished safeAnimate(drawer, { y: [128, 0], opacity: 1 }, { duration: 0.5 })?.finished
]); ]);
await sleep(1000); await sleep(250);
await safeAnimate(uploadBtn, { scale: [1, 0.9, 1] }, { duration: 0.25 })?.finished; await safeAnimate(uploadBtn, { scale: [1, 0.9, 1] }, { duration: 0.25 })?.finished;
@@ -75,7 +75,7 @@ const execute = async () => {
safeAnimate(upload, { y: [-16, 0], opacity: 1 }, { duration: 0.5 })?.finished safeAnimate(upload, { y: [-16, 0], opacity: 1 }, { duration: 0.5 })?.finished
]); ]);
await sleep(500); await sleep(250);
await safeAnimate(box, { x: 300, y: 300 }, { duration: 0 })?.finished; await safeAnimate(box, { x: 300, y: 300 }, { duration: 0 })?.finished;
@@ -84,14 +84,14 @@ const execute = async () => {
safeAnimate(box, { y: [300 - 16, 300], opacity: 1 }, { duration: 1 })?.finished safeAnimate(box, { y: [300 - 16, 300], opacity: 1 }, { duration: 1 })?.finished
]); ]);
await sleep(500); await sleep(250);
await Promise.all([ await Promise.all([
safeAnimate(uploadText, { opacity: 0 }, { duration: 0.5 })?.finished, safeAnimate(uploadText, { opacity: 0 }, { duration: 0.5 })?.finished,
safeAnimate(uploadLoading, { opacity: 1 }, { duration: 0.5 })?.finished, safeAnimate(uploadLoading, { opacity: 1 }, { duration: 0.5 })?.finished,
safeAnimate(uploadImg, { opacity: 0, y: 64 + 8 }, { duration: 0.5 })?.finished safeAnimate(uploadImg, { opacity: 0, y: 64 + 8 }, { duration: 0.5 })?.finished
]); ]);
await sleep(500); await sleep(250);
await safeAnimate(upload, { opacity: 0, y: 48 }, { duration: 0.5 })?.finished; await safeAnimate(upload, { opacity: 0, y: 48 }, { duration: 0.5 })?.finished;
@@ -108,7 +108,7 @@ const execute = async () => {
] ]
})); }));
await sleep(1000); await sleep(250);
update((p) => ({ update((p) => ({
...p, ...p,

View File

@@ -13,7 +13,7 @@
onMount(() => { onMount(() => {
let frame: number | null = null; let frame: number | null = null;
const ease = () => { const ease = () => {
easedPercentage += (percentage - easedPercentage) * 0.1; easedPercentage += (percentage - easedPercentage);
frame = window.requestAnimationFrame(ease); frame = window.requestAnimationFrame(ease);
}; };
ease(); ease();

View File

@@ -47,28 +47,58 @@
next(); next();
} }
} }
let isEnd = false;
let isStart = true;
function handleScroll() {
if (carousel.scrollLeft === 0) {
isStart = true;
isEnd = false;
} else if (Math.ceil(carousel.scrollLeft + carousel.offsetWidth) >= carousel.scrollWidth) {
isStart = false;
isEnd = true;
} else {
isStart = false;
isEnd = false;
}
}
</script> </script>
<div class="u-flex u-main-space-between u-flex-wrap"> <slot name="header" />
<slot name="header" />
<div class="u-flex u-gap-12 u-cross-end u-margin-block-start-8"> <div>
<button class="aw-icon-button" aria-label="Move carousel backward" on:click={() => prev()}> <div class="u-flex u-main-end u-flex-wrap">
<span class="icon-arrow-left" aria-hidden="true" /> <div class="u-flex u-gap-12 u-cross-end u-margin-block-start-8">
</button> <button
<button class="aw-icon-button" aria-label="Move carousel forward" on:click={() => next()}> class="aw-icon-button"
<span class="icon-arrow-right" aria-hidden="true" /> aria-label="Move carousel backward"
</button> disabled={isStart}
on:click={() => prev()}
>
<span class="aw-icon-arrow-left" aria-hidden="true" />
</button>
<button
class="aw-icon-button"
aria-label="Move carousel forward"
disabled={isEnd}
on:click={() => next()}
>
<span class="aw-icon-arrow-right" aria-hidden="true" />
</button>
</div>
</div> </div>
<ul
class="aw-grid-articles aw-u-gap-32 u-margin-block-start-32 carousel"
bind:this={carousel}
on:touchstart={handleTouchStart}
on:touchmove={handleTouchMove}
on:touchend={handleTouchEnd}
on:scroll={handleScroll}
>
<slot />
</ul>
</div> </div>
<ul
class="aw-grid-articles aw-u-gap-32 u-margin-block-start-32 carousel"
bind:this={carousel}
on:touchstart={handleTouchStart}
on:touchmove={handleTouchMove}
on:touchend={handleTouchEnd}
>
<slot />
</ul>
<style lang="scss"> <style lang="scss">
.carousel { .carousel {

View File

@@ -1,3 +1,19 @@
<script lang="ts">
import type { Action } from 'svelte/action';
const accordion: Action<HTMLButtonElement> = (node) => {
const callback = () => {
node.classList.toggle('is-open');
};
node.addEventListener('click', callback);
return {
destroy() {
node.removeEventListener('click', callback);
}
};
};
</script>
<nav class="aw-footer-nav u-margin-block-start-100 u-position-relative aw-u-sep-block-start"> <nav class="aw-footer-nav u-margin-block-start-100 u-position-relative aw-u-sep-block-start">
<img class="aw-logo" src="/images/logos/appwrite.svg" alt="appwrite" width="130" /> <img class="aw-logo" src="/images/logos/appwrite.svg" alt="appwrite" width="130" />
<ul class="aw-footer-nav-main-list"> <ul class="aw-footer-nav-main-list">
@@ -5,7 +21,7 @@
<h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow"> <h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">
Quick starts Quick starts
</h5> </h5>
<button class="aw-footer-nav-button aw-is-only-mobile"> <button class="aw-footer-nav-button aw-is-only-mobile" use:accordion>
<span class="aw-caption-500 aw-eyebrow">Quick starts</span> <span class="aw-caption-500 aw-eyebrow">Quick starts</span>
<svg <svg
class="aw-footer-nav-button-arrow" class="aw-footer-nav-button-arrow"
@@ -58,7 +74,7 @@
</li> </li>
<li class="aw-footer-nav-main-item"> <li class="aw-footer-nav-main-item">
<h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">Products</h5> <h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">Products</h5>
<button class="aw-footer-nav-button aw-is-only-mobile"> <button class="aw-footer-nav-button aw-is-only-mobile" use:accordion>
<span class="aw-caption-500 aw-eyebrow">Products</span> <span class="aw-caption-500 aw-eyebrow">Products</span>
<svg <svg
class="aw-footer-nav-button-arrow" class="aw-footer-nav-button-arrow"
@@ -126,7 +142,7 @@
</li> </li>
<li class="aw-footer-nav-main-item"> <li class="aw-footer-nav-main-item">
<h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">About</h5> <h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">About</h5>
<button class="aw-footer-nav-button is-open aw-is-only-mobile"> <button class="aw-footer-nav-button is-open aw-is-only-mobile" use:accordion>
<span class="aw-caption-500 aw-eyebrow">About</span> <span class="aw-caption-500 aw-eyebrow">About</span>
<svg <svg
class="aw-footer-nav-button-arrow" class="aw-footer-nav-button-arrow"
@@ -147,8 +163,8 @@
<ul class="aw-footer-nav-secondary-list aw-sub-body-400"> <ul class="aw-footer-nav-secondary-list aw-sub-body-400">
<li><a class="aw-link" href="/pricing">Pricing</a></li> <li><a class="aw-link" href="/pricing">Pricing</a></li>
<li><a class="aw-link" href="/company">Company</a></li> <li><a class="aw-link" href="/company">Company</a></li>
<li><a class="aw-link" href="/assets">Brand</a></li> <li><a class="aw-link" href="https://careers.appwrite.io/" target="_blank">Careers</a></li>
<li><a class="aw-link" href="/careers">Careers</a></li> <li><a class="aw-link" href="/heroes">Heroes</a></li>
<li> <li>
<a class="aw-link" href="https://store.appwrite.io" target="_blank">Store</a> <a class="aw-link" href="https://store.appwrite.io" target="_blank">Store</a>
</li> </li>
@@ -159,7 +175,7 @@
</li> </li>
<li class="aw-footer-nav-main-item"> <li class="aw-footer-nav-main-item">
<h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">Policies</h5> <h5 class="aw-footer-nav-main-title aw-is-not-mobile aw-caption-500 aw-eyebrow">Policies</h5>
<button class="aw-footer-nav-button aw-is-only-mobile"> <button class="aw-footer-nav-button aw-is-only-mobile" use:accordion>
<span class="aw-caption-500 aw-eyebrow">Policies</span> <span class="aw-caption-500 aw-eyebrow">Policies</span>
<svg <svg
class="aw-footer-nav-button-arrow" class="aw-footer-nav-button-arrow"

View File

@@ -33,7 +33,7 @@
<div class="info aw-caption-500" /> <div class="info aw-caption-500" />
</div> </div>
<p class="aw-strip-plans-info aw-caption-500"> <p class="aw-strip-plans-info aw-caption-500">
For personal, passion projects and non-commercial use. For personal passion projects and students.
</p> </p>
<a href="https://cloud.appwrite.io/register" class="aw-button is-full-width-mobile aw-u-cross-child-end"> <a href="https://cloud.appwrite.io/register" class="aw-button is-full-width-mobile aw-u-cross-child-end">
<span class="text">Get Started</span> <span class="text">Get Started</span>
@@ -48,7 +48,7 @@
<div class="info aw-caption-500">per org member/month</div> <div class="info aw-caption-500">per org member/month</div>
</div> </div>
<p class="aw-strip-plans-info aw-caption-500"> <p class="aw-strip-plans-info aw-caption-500">
For pro developers and production projects that need the ability to scale. For pro developers and teams that need to scale their products.
</p> </p>
<button class="aw-button is-full-width-mobile is-secondary aw-u-cross-child-end" disabled> <button class="aw-button is-full-width-mobile is-secondary aw-u-cross-child-end" disabled>
<span class="text">Coming soon</span> <span class="text">Coming soon</span>

View File

@@ -56,7 +56,11 @@
</a> </a>
{/if} {/if}
{#if nextStep} {#if nextStep}
<a href={nextStep.href} class="aw-button is-secondary"> <a
href={nextStep.href}
class="aw-button is-secondary"
style:margin-left={prevStep ? undefined : 'auto'}
>
<span class="aw-sub-body-500"> <span class="aw-sub-body-500">
Step {nextStep.step}<span class="aw-is-not-mobile">: {nextStep.title}</span> Step {nextStep.step}<span class="aw-is-not-mobile">: {nextStep.title}</span>
</span> </span>

View File

@@ -1,8 +1,11 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
import { writable } from 'svelte/store';
export type NavLink = { export type NavLink = {
label: string; label: string;
href: string; href: string;
}; };
export const isHeaderHidden = writable(false);
</script> </script>
<script lang="ts"> <script lang="ts">
@@ -101,7 +104,7 @@
const scrollInfo = createScrollInfo(); const scrollInfo = createScrollInfo();
$: isHeaderHidden = (() => { $: $isHeaderHidden = (() => {
if ($scrollInfo.top < 250) { if ($scrollInfo.top < 250) {
return false; return false;
} }
@@ -117,7 +120,7 @@
<section <section
class="aw-mobile-header theme-{resolvedTheme}" class="aw-mobile-header theme-{resolvedTheme}"
class:is-transparent={browser && !isMobileNavOpen} class:is-transparent={browser && !isMobileNavOpen}
class:is-hidden={isHeaderHidden} class:is-hidden={$isHeaderHidden}
> >
<div class="aw-mobile-header-start"> <div class="aw-mobile-header-start">
<a href="/"> <a href="/">
@@ -157,7 +160,7 @@
<header <header
class="aw-main-header theme-{resolvedTheme}" class="aw-main-header theme-{resolvedTheme}"
class:is-transparent={browser} class:is-transparent={browser}
class:is-hidden={isHeaderHidden} class:is-hidden={$isHeaderHidden}
> >
<!-- <div class="aw-top-banner"> <!-- <div class="aw-top-banner">
<div class="aw-top-banner-content aw-u-color-text-primary"> <div class="aw-top-banner-content aw-u-color-text-primary">
@@ -199,7 +202,11 @@
</nav> </nav>
</div> </div>
<div class="aw-main-header-end"> <div class="aw-main-header-end">
<a href="https://github.com/appwrite/appwrite/stargazers" target="_blank" class="aw-button is-text"> <a
href="https://github.com/appwrite/appwrite/stargazers"
target="_blank"
class="aw-button is-text"
>
<span aria-hidden="true" class="aw-icon-star" /> <span aria-hidden="true" class="aw-icon-star" />
<span class="text">Star on GitHub</span> <span class="text">Star on GitHub</span>
<span class="aw-inline-tag aw-sub-body-400">33.2K</span> <span class="aw-inline-tag aw-sub-body-400">33.2K</span>

View File

@@ -3,6 +3,7 @@
label: string; label: string;
href: string; href: string;
icon?: string; icon?: string;
isParent?: boolean;
}; };
export type NavGroup = { export type NavGroup = {
@@ -32,7 +33,7 @@
} }
</script> </script>
<nav class="aw-side-nav" class:is-transparent={!expandable}> <nav class="aw-side-nav">
<div class="aw-side-nav-wrapper"> <div class="aw-side-nav-wrapper">
<button class="aw-input-text aw-is-not-desktop"> <button class="aw-input-text aw-is-not-desktop">
<span class="icon-search" /> <span class="icon-search" />

View File

@@ -13,5 +13,8 @@
{#if groupItem.icon} {#if groupItem.icon}
<span class={groupItem.icon} aria-hidden="true" /> <span class={groupItem.icon} aria-hidden="true" />
{/if} {/if}
<span class="aw-caption-400">{groupItem.label}</span> <span class="aw-caption-400">{groupItem.label} </span>
{#if groupItem.isParent}
<span class="icon-cheveron-right u-margin-inline-start-auto" aria-hidden="true" />
{/if}
</a> </a>

View File

@@ -8,6 +8,7 @@
author: string; author: string;
category: string; category: string;
href: string; href: string;
featured?: boolean;
}; };
</script> </script>
@@ -84,7 +85,7 @@
<p class="aw-caption-400">{authorData.role}</p> <p class="aw-caption-400">{authorData.role}</p>
</div> </div>
</a> </a>
<ul class="u-flex u-gap-8 u-margin-inline-start-auto u-cross-child-center"> <!-- <ul class="u-flex u-gap-8 u-margin-inline-start-auto u-cross-child-center">
{#if authorData.twitter} {#if authorData.twitter}
<li> <li>
<a <a
@@ -124,7 +125,7 @@
</a> </a>
</li> </li>
{/if} {/if}
</ul> </ul> -->
</div> </div>
{/if} {/if}
</header> </header>
@@ -138,13 +139,13 @@
<slot /> <slot />
</div> </div>
</article> </article>
{#if categories?.length} <!-- {#if categories?.length}
<div class="u-flex u-gap-16"> <div class="u-flex u-gap-16">
{#each categories as cat} {#each categories as cat}
<a href={cat.href} class="aw-tag">{cat.name}</a> <a href={cat.href} class="aw-tag">{cat.name}</a>
{/each} {/each}
</div> </div>
{/if} {/if} -->
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1 +1 @@
<li><slot /></li> <li><p><slot /></p></li>

View File

@@ -1,6 +1,4 @@
<script lang="ts"> <script lang="ts">
import { getContext, hasContext } from 'svelte';
export let href: string; export let href: string;
export let title: string; export let title: string;
@@ -11,7 +9,7 @@
<a class="aw-link" {href} {title} {target} {rel}> <a class="aw-link" {href} {title} {target} {rel}>
<slot /> <slot />
{#if isExternal} {#if !isExternal}
<!-- <span class="icon-cheveron-right" /> --> <!-- <span class="icon-cheveron-right" /> -->
{/if} {/if}
</a> </a>

View File

@@ -1,21 +1,10 @@
{% info title="Account vs Users API" %} {% info title="Account vs Users API" %}
Appwrite provides two APIs to manager user accounts. The Account API is the API you should use in your **client applications** with [Client SDKs](/docs/sdks#client) like web, Flutter, mobile, and native apps.
The Account API is the API you should use in your **client applications** like web, Flutter, mobile, and native apps.
Account API creates sessions, which represent an authenticated user and is attached to a user's [account](/docs/products/auth/accounts). Account API creates sessions, which represent an authenticated user and is attached to a user's [account](/docs/products/auth/accounts).
Sessions respect [permissions](/docs/advanced/platform/permissions), which means users can only access resources if they have been granted the correct permissions. Sessions respect [permissions](/docs/advanced/platform/permissions), which means users can only access resources if they have been granted the correct permissions.
You'll notice that the Account API doesn't allow you to view or make changes to other users. The Users API is a dedicated API for managing users from an admin's perspective.
This is by design and for **security reasons**. It should be used with backend or server-side applications with [Server SDKs](/docs/sdks#server). Users API uses API keys instead of sessions.
[Account API references](/docs/references/cloud/client-web/account)
The Users API is a dedicated API for managing users from an admin's perspective. **Do not use the Users API on client applications**.
It should be used with backend or server-side applications with the [Server SDK](#).
Users API uses API keys instead of sessions.
This means they're not resticted by permissions, but by the scopes granted to the API key used. This means they're not resticted by permissions, but by the scopes granted to the API key used.
[Users API references](/docs/references/cloud/server-nodejs/users)
{% /info %} {% /info %}

View File

@@ -9,6 +9,13 @@
import '@fontsource/inter/800.css'; import '@fontsource/inter/800.css';
import '@fontsource/inter/900.css'; import '@fontsource/inter/900.css';
import '$scss/index.scss'; import '$scss/index.scss';
import { dev } from '$app/environment';
</script> </script>
<svelte:head>
{#if !dev}
<script defer data-domain="appwrite.io" src="https://plausible.io/js/script.js"></script>
{/if}
</svelte:head>
<slot /> <slot />

View File

@@ -31,7 +31,7 @@
/> />
</div> </div>
<div <!-- <div
class="u-position-absolute" class="u-position-absolute"
style="top: 15rem; left: 50%; translate: calc(-50% - 900px); width: 75.9375rem;" style="top: 15rem; left: 50%; translate: calc(-50% - 900px); width: 75.9375rem;"
> >
@@ -43,14 +43,17 @@
style="top: 60rem; left: 50%; translate: calc(-50% + 800px); width: 60rem;" style="top: 60rem; left: 50%; translate: calc(-50% + 800px); width: 60rem;"
> >
<img src="/images/bgs/hero-lines-2.png" alt="" /> <img src="/images/bgs/hero-lines-2.png" alt="" />
</div> </div> -->
<Main> <Main>
<div class="aw-big-padding-section"> <div class="aw-big-padding-section">
<div class="aw-big-padding-section-level-1"> <div class="aw-big-padding-section-level-1">
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">
<section class="aw-container aw-u-padding-block-end-0"> <section class="aw-container aw-u-padding-block-end-0">
<a href="/blog/post/meet-the-new-appwrite" class="aw-hero-banner-button aw-u-margin-block-end-24"> <a
href="/blog/post/meet-the-new-appwrite"
class="aw-hero-banner-button aw-u-margin-block-end-24"
>
<span class="aw-icon-star" aria-hidden="true" /> <span class="aw-icon-star" aria-hidden="true" />
<span class="aw-caption-500">New</span> <span class="aw-caption-500">New</span>
<div class="aw-hero-banner-button-sep" /> <div class="aw-hero-banner-button-sep" />
@@ -171,7 +174,7 @@
Self-host your data or take it to the Cloud Self-host your data or take it to the Cloud
</h2> </h2>
<p class="aw-description u-max-width-700"> <p class="aw-description u-max-width-700">
Migrate your data from and to any platform at any time with Appwrites migrations API. Migrate your data from and to any platform at any time with Appwrite Migrations.
With built-in security and privacy for peace of mind. With built-in security and privacy for peace of mind.
</p> </p>
</section> </section>
@@ -180,7 +183,9 @@
<li class="aw-info-boxes-item"> <li class="aw-info-boxes-item">
<img src="/images/icons/gradients/self-hosted.svg" width="40" height="40" alt="" /> <img src="/images/icons/gradients/self-hosted.svg" width="40" height="40" alt="" />
<h3 class="aw-info-boxes-title">Self-Hosted</h3> <h3 class="aw-info-boxes-title">Self-Hosted</h3>
<p class="aw-info-boxes-content">Own your data or host it on a cloud region of choice.</p> <p class="aw-info-boxes-content">
Own your data or host it on a cloud region of choice.
</p>
</li> </li>
<li class="aw-info-boxes-item"> <li class="aw-info-boxes-item">
<img src="/images/icons/gradients/lock.svg" width="40" height="40" alt="" /> <img src="/images/icons/gradients/lock.svg" width="40" height="40" alt="" />
@@ -239,7 +244,7 @@
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">
<div class="aw-container"> <div class="aw-container">
<div class="aw-hero"> <div class="aw-hero">
<div class="aw-display aw-u-color-text-primary">Loved by developers</div> <div class="aw-display aw-u-color-text-primary">Loved by our community</div>
</div> </div>
<ul class="aw-multi-columns-1 aw-u-margin-block-start-80"> <ul class="aw-multi-columns-1 aw-u-margin-block-start-80">
<li> <li>
@@ -249,9 +254,9 @@
icon="product-hunt" icon="product-hunt"
avatarSrc="/images/community/avatars/terry.png" avatarSrc="/images/community/avatars/terry.png"
> >
Been a huge supporter of Appwrite for over a year, championing Been a huge supporter of Appwrite for over a year, championing it even at the
it even at the companies I was working at. Their community is second-to-none, companies I was working at. Their community is second-to-none, speed of feature
speed of feature release is exceptional, and the support in their Discord is incredible. release is exceptional, and the support in their Discord is incredible.
</DeveloperCard> </DeveloperCard>
</li> </li>
<li> <li>
@@ -261,7 +266,9 @@
icon="linkedin" icon="linkedin"
avatarSrc="/images/community/avatars/varun.png" 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! 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!
</DeveloperCard> </DeveloperCard>
</li> </li>
<li> <li>
@@ -271,7 +278,12 @@
icon="x" icon="x"
avatarSrc="/images/community/avatars/kap.png" 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 href="https://twitter.com/appwrite" target="_blank" class="aw-link-1">@appwrite</a> handle my authentication process while I focus on the business logic. 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
href="https://twitter.com/appwrite"
target="_blank"
class="aw-link-1">@appwrite</a
> handle my authentication process while I focus on the business logic.
</DeveloperCard> </DeveloperCard>
</li> </li>
<li> <li>
@@ -291,7 +303,9 @@
icon="product-hunt" icon="product-hunt"
avatarSrc="/images/community/avatars/terieyenike.png" 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> </DeveloperCard>
</li> </li>
<li> <li>
@@ -301,8 +315,12 @@
icon="x" icon="x"
avatarSrc="/images/community/avatars/souvik.png" avatarSrc="/images/community/avatars/souvik.png"
> >
If you're looking for a backend server that is both powerful and easy to use, check out <a href="https://twitter.com/appwrite" target="_blank" class="aw-link-1">@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. If you're looking for a backend server that is both powerful and easy to use, check
</DeveloperCard> out <a href="https://twitter.com/appwrite" target="_blank" class="aw-link-1"
>@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.
</DeveloperCard>
</li> </li>
</ul> </ul>
</div> </div>
@@ -313,7 +331,10 @@
<Spline let:fallback let:viewer> <Spline let:fallback let:viewer>
<div <div
class="u-position-absolute aw-is-not-mobile" class="u-position-absolute aw-is-not-mobile"
style="inline-size:512px; block-size: 512px; inset-block-start:6rem; inset-inline-start:calc(100% - 500px)" style:inline-size="512px"
style:block-size="512px"
style:inset-block-start="8rem"
style:left="calc(50% - 256px + 18rem)"
> >
<img <img
src="/images/animations/tech.png" src="/images/animations/tech.png"
@@ -323,9 +344,10 @@
style="position: absolute; display: block;" style="position: absolute; display: block;"
use:fallback use:fallback
/> />
<spline-viewer <spline-viewer
url="https://prod.spline.design/KvoQWZAi5foGUXxJ/scene.splinecode" url="https://prod.spline.design/KvoQWZAi5foGUXxJ/scene.splinecode"
loading="eager"
use:viewer use:viewer
/> />
</div> </div>
@@ -406,13 +428,18 @@
</div> </div>
</div> </div>
<div class="aw-big-padding-section-level-2 u-position-relative u-overflow-hidden"> <div class="aw-big-padding-section-level-2 u-position-relative u-overflow-hidden">
<Spline let:viewer let:fallback> <Spline let:viewer>
<div class="u-position-absolute u-z-index-0" style="width: 50%; height:100%; left:0;"> <div
class="u-position-absolute u-z-index-0 aw-is-not-mobile"
style:width="50%"
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%">
<spline-viewer <spline-viewer
url="https://prod.spline.design/OQpkUefWdEWkbi4d/scene.splinecode" url="https://prod.spline.design/OQpkUefWdEWkbi4d/scene.splinecode"
use:viewer
loading="eager" loading="eager"
use:viewer
/> />
</div> </div>
</div> </div>
@@ -422,7 +449,9 @@
<div class="grid-1-1"> <div class="grid-1-1">
<section class="aw-hero is-align-start"> <section class="aw-hero is-align-start">
<span class="aw-badges aw-eyebrow">Scale_</span> <span class="aw-badges aw-eyebrow">Scale_</span>
<h2 class="aw-display u-max-width-600 aw-u-color-text-primary">We scale for you and your users</h2> <h2 class="aw-display u-max-width-600 aw-u-color-text-primary">
We scale for you and your users
</h2>
</section> </section>
<ul <ul
class="aw-big-list-info u-margin-inline-start-auto aw-u-inline-width-100-percent-mobile-break1 aw-u-margin-block-start-48" class="aw-big-list-info u-margin-inline-start-auto aw-u-inline-width-100-percent-mobile-break1 aw-u-margin-block-start-48"

View File

@@ -3,6 +3,8 @@
import { MainFooter, FooterNav, Article } from '$lib/components'; import { MainFooter, FooterNav, Article } from '$lib/components';
export let data; export let data;
const featured = data.posts.find((post) => post.featured);
</script> </script>
<Main> <Main>
@@ -59,68 +61,70 @@
<div class="aw-big-padding-section-level-2 u-position-relative"> <div class="aw-big-padding-section-level-2 u-position-relative">
<div class="aw-container"> <div class="aw-container">
<h1 class="aw-display aw-u-color-text-primary">Blog</h1> <h1 class="aw-display aw-u-color-text-primary">Blog</h1>
<article class="aw-feature-article u-margin-block-start-48"> {#if featured}
<div class="aw-feature-article-image"> {@const author = data.authors.find((author) => author.slug === featured.author)}
<img src="/images/blog/placeholder.png" class="aw-image-ratio-4/3" alt="cover" /> <article class="aw-feature-article u-margin-block-start-48">
</div> <a href={featured.href} class="aw-feature-article-image">
<div class="aw-feature-article-content"> <img src={featured.cover} class="aw-image-ratio-4/3" alt="cover" />
<header class="aw-feature-article-header"> </a>
<ul class="aw-metadata aw-caption-400 aw-is-only-mobile"> <div class="aw-feature-article-content">
<li>[data]</li> <header class="aw-feature-article-header">
<li>[time-to-read] min</li> <ul class="aw-metadata aw-caption-400 aw-is-only-mobile">
</ul> <li>{featured.timeToRead} min</li>
<h2 class="aw-title aw-u-color-text-primary">Lorem ipsum dolor sit amet</h2> </ul>
</header> <a href={featured.href}>
<p class="aw-sub-body-400"> <h2 class="aw-title aw-u-color-text-primary">{featured.title}</h2>
Lorem ipsum dolor sit amet consectetur. Mauris eu sit gravida dignissim semper </a>
euismod. Imperdiet eget rhoncus eget purus. </header>
</p> <p class="aw-sub-body-400">
<div class="aw-author"> {featured.description}
<div class="u-flex u-cross-center u-gap-8"> </p>
<img <div class="aw-author">
class="aw-author-image" <div class="u-flex u-cross-center u-gap-8">
src="/images/blog/placeholder.png" <img
width="24" class="aw-author-image"
height="24" src={author?.avatar}
alt="" width="24"
/> height="24"
<div class="aw-author-info"> alt=""
<h4 class="aw-sub-body-400 aw-u-color-text-primary">Authors name</h4> />
<p class="aw-caption-400 u-hide">Author's role or bio</p> <div class="aw-author-info">
<ul class="aw-metadata aw-caption-400 aw-is-not-mobile"> <a href={author?.href} class="aw-sub-body-400 aw-link">{author?.name}</a>
<li>[data]</li> <p class="aw-caption-400 u-hide">{author?.bio}</p>
<li>[time-to-read] min</li> <ul class="aw-metadata aw-caption-400 aw-is-not-mobile">
</ul> <li>{featured.timeToRead} min</li>
</ul>
</div>
</div> </div>
<ul class="u-flex u-gap-8 u-margin-inline-start-auto u-hide">
<li>
<a
href="https://twitter.com/appwrite"
class="aw-icon-button"
aria-label="Author twitter"
target="_blank"
>
<span class="aw-icon-x" aria-hidden="true" />
</a>
</li>
<li>
<a
href="https://twitter.com/appwrite"
class="aw-icon-button"
aria-label="Author LinkedIn"
target="_blank"
>
<span class="aw-icon-linkedin" aria-hidden="true" />
</a>
</li>
</ul>
</div> </div>
<ul class="u-flex u-gap-8 u-margin-inline-start-auto u-hide"> <button class="aw-button is-secondary u-margin-block-start-auto">
<li> <span>Read article</span>
<a </button>
href="https://twitter.com/appwrite"
class="aw-icon-button"
aria-label="Author twitter"
target="_blank"
>
<span class="aw-icon-x" aria-hidden="true" />
</a>
</li>
<li>
<a
href="https://twitter.com/appwrite"
class="aw-icon-button"
aria-label="Author LinkedIn"
target="_blank"
>
<span class="aw-icon-linkedin" aria-hidden="true" />
</a>
</li>
</ul>
</div> </div>
<button class="aw-button is-secondary u-margin-block-start-auto"> </article>
<span>Read article</span> {/if}
</button>
</div>
</article>
</div> </div>
</div> </div>
</div> </div>
@@ -230,9 +234,7 @@
<div class="u-margin-block-start-48"> <div class="u-margin-block-start-48">
<ul class="aw-grid-articles"> <ul class="aw-grid-articles">
{#each data.posts as post} {#each data.posts as post}
{@const author = data.authors.find( {@const author = data.authors.find((author) => author.slug === post.author)}
(author) => author.slug === post.author
)}
{#if author} {#if author}
<Article <Article
title={post.title} title={post.title}
@@ -247,16 +249,6 @@
{/each} {/each}
</ul> </ul>
</div> </div>
<div class="u-flex u-main-end aw-u-margin-block-start-48">
<div class="aw-select is-colored">
<button class="physical-select">
<span class="icon-moon" aria-hidden="true" />
<span data-svelte-h="svelte-397x2m">Dark</span>
</button>
<span class="icon-cheveron-down" aria-hidden="true" />
</div>
</div>
</div> </div>
</div> </div>
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">

View File

@@ -21,6 +21,7 @@ export function load() {
return { return {
title: frontmatter.title, title: frontmatter.title,
description: frontmatter.description, description: frontmatter.description,
featured: frontmatter?.featured ?? false,
date: new Date(frontmatter.date), date: new Date(frontmatter.date),
cover: frontmatter.cover, cover: frontmatter.cover,
timeToRead: frontmatter.timeToRead, timeToRead: frontmatter.timeToRead,

View File

@@ -7,6 +7,7 @@ cover: /images/blog/logo.png
timeToRead: 5 timeToRead: 5
author: sara-kaandorp author: sara-kaandorp
category: design, brand category: design, brand
featured: true
--- ---
At Appwrite, we are constantly collaborating with the Appwrite community to improve Appwrite's products, services, and content. All for the sake of improving your developer experience, as well as staying true to the open-source values. At Appwrite, we are constantly collaborating with the Appwrite community to improve Appwrite's products, services, and content. All for the sake of improving your developer experience, as well as staying true to the open-source values.

View File

@@ -2,11 +2,10 @@
import { Main } from '$lib/layouts'; import { Main } from '$lib/layouts';
import MainFooter from '$lib/components/MainFooter.svelte'; import MainFooter from '$lib/components/MainFooter.svelte';
import FooterNav from '$lib/components/FooterNav.svelte'; import FooterNav from '$lib/components/FooterNav.svelte';
import { Tabs } from '$lib/UI';
import PreFooter from '$lib/components/PreFooter.svelte'; import PreFooter from '$lib/components/PreFooter.svelte';
import { Carousel } from '$lib/components';
</script> </script>
<Main> <Main>
<div class="aw-big-padding-section"> <div class="aw-big-padding-section">
<div class="aw-big-padding-section-level-1"> <div class="aw-big-padding-section-level-1">
@@ -18,15 +17,19 @@
</h1> </h1>
<div class=""> <div class="">
<p class="aw-description"> <p class="aw-description">
Inspire and get inspired. Join our community of maintainers and contributors Inspire and get inspired. Join our community of maintainers and contributors and
and help us make Appwrite better for developers all around the world. help us make Appwrite better for developers worldwide.
</p> </p>
<div class="u-flex u-flex-wrap u-gap-12 u-margin-block-start-32"> <div class="u-flex u-flex-wrap u-gap-12 u-margin-block-start-32">
<a href="/discord" target="_blank" class="aw-button is-full-width-mobile"> <a href="/discord" target="_blank" class="aw-button is-full-width-mobile">
<span class="text">Join our Discord</span> <span class="text">Join our Discord</span>
</a> </a>
<a href="https://github.com/appwrite/appwrite/stargazers" target="_blank" class="aw-button is-secondary is-full-width-mobile"> <a
<span aria-hidden="true" class="aw-icon-star"></span> href="https://github.com/appwrite/appwrite/stargazers"
target="_blank"
class="aw-button is-secondary is-full-width-mobile"
>
<span aria-hidden="true" class="aw-icon-star" />
<span>Star on GitHub</span> <span>Star on GitHub</span>
<span class="aw-inline-tag aw-sub-body-400">33.2K</span> <span class="aw-inline-tag aw-sub-body-400">33.2K</span>
</a> </a>
@@ -37,8 +40,7 @@
</div> </div>
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">
<section class="aw-container"> <section class="aw-container">
<ul class="aw-grid-row-4 aw-grid-row-4-mobile-2" <ul class="aw-grid-row-4 aw-grid-row-4-mobile-2" style="--gap-mobile:1.5rem;">
style="--gap-mobile:1.5rem;">
<li> <li>
<div class="aw-card is-normal"> <div class="aw-card is-normal">
<div class="aw-title aw-u-color-text-primary">33K+</div> <div class="aw-title aw-u-color-text-primary">33K+</div>
@@ -87,7 +89,6 @@
<div class="aw-description">Contributors</div> <div class="aw-description">Contributors</div>
</div> </div>
</li> </li>
</ul> </ul>
</section> </section>
</div> </div>
@@ -102,10 +103,14 @@
</h1> </h1>
<div class=""> <div class="">
<p class="aw-description"> <p class="aw-description">
Appwrite improves daily thanks to our diverse, inspiring contributors. They come from various backgrounds and experience levels, welcoming anyone to join and help us excel. See contributors of Appwrite since 2019 and discover how you can start contributing.
</p> </p>
<div class="u-flex u-flex-wrap u-main-center u-gap-12 u-margin-block-start-32"> <div class="u-flex u-flex-wrap u-main-center u-gap-12 u-margin-block-start-32">
<a href="https://github.com/appwrite/appwrite/graphs/contributors" target="_blank" class="aw-button is-secondary is-full-width-mobile"> <a
href="https://github.com/appwrite/appwrite/graphs/contributors"
target="_blank"
class="aw-button is-secondary is-full-width-mobile"
>
<span>View all contributors</span> <span>View all contributors</span>
</a> </a>
</div> </div>
@@ -119,34 +124,42 @@
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">
<div class="aw-container"> <div class="aw-container">
<div class="aw-hero is-align-start"> <div class="aw-hero is-align-start">
<h2 class="aw-display aw-u-color-text-primary"> <h2 class="aw-display aw-u-color-text-primary">Get Involved</h2>
Get Involved
</h2>
<div class=""> <div class="">
<p class="aw-description"> <p class="aw-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin in ultrices lacus. Duis pellentesque quis purus in posuere. With every contribution, Appwrite gets better for all of us. Start contributing
today.
</p> </p>
</div> </div>
</div> </div>
<div class="aw-card is-normal u-margin-block-start-32" style="--card-padding:2rem; --card-padding-mobile:1.25rem;"> <div
<div class="u-flex aw-u-flex-direction-column-mobile class="aw-card is-normal u-margin-block-start-32"
aw-u-gap-96 aw-u-row-gap-48"> style="--card-padding:2rem; --card-padding-mobile:1.25rem;"
>
<div
class="u-flex aw-u-flex-direction-column-mobile
aw-u-gap-96 aw-u-row-gap-48"
>
<div> <div>
<h3 class="aw-label aw-u-color-text-primary">Check our Open Issues</h3> <h3 class="aw-label aw-u-color-text-primary">Check our Open Issues</h3>
<p class="aw-main-body-500 u-margin-block-start-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> <p class="aw-main-body-500 u-margin-block-start-4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<button class="aw-button is-secondary u-margin-block-start-32"> <button class="aw-button is-secondary u-margin-block-start-32">
<span class="aw-icon-github" aria-hidden="true"></span> <span class="aw-icon-github" aria-hidden="true" />
<span class="">View all Open Issues</span> <span class="">View all Open Issues</span>
</button> </button>
</div> </div>
<div class="u-stretch"> <div class="u-stretch">
<table class="aw-table-line"> <table class="aw-table-line">
<thead class="aw-table-line-head"> <thead class="aw-table-line-head">
<tr class="aw-table-line-row"> <tr class="aw-table-line-row">
<th class="aw-table-line-cell aw-u-color-text-primary u-un-break-text">Issue #</th> <th class="aw-table-line-cell aw-u-color-text-primary u-un-break-text"
<th class="aw-table-line-cell aw-u-color-text-primary">Title</th> >Issue #</th
</tr> >
<th class="aw-table-line-cell aw-u-color-text-primary">Title</th>
</tr>
</thead> </thead>
<tbody class="aw-table-line-body"> <tbody class="aw-table-line-body">
<tr class="aw-table-line-row"> <tr class="aw-table-line-row">
@@ -155,7 +168,9 @@
</td> </td>
<td class="aw-table-line-cell"> <td class="aw-table-line-cell">
<div> <div>
<span class="aw-sub-body-500 aw-u-color-text-accent-click">Create a Helm Chart for Appwrite</span> <span class="aw-sub-body-500 aw-u-color-text-accent-click"
>Create a Helm Chart for Appwrite</span
>
<span>(appwrite/appwrite)</span> <span>(appwrite/appwrite)</span>
</div> </div>
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8"> <ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8">
@@ -177,7 +192,9 @@
</td> </td>
<td class="aw-table-line-cell"> <td class="aw-table-line-cell">
<div> <div>
<span class="aw-sub-body-500 aw-u-color-text-accent-click">Create a Helm Chart for Appwrite</span> <span class="aw-sub-body-500 aw-u-color-text-accent-click"
>Create a Helm Chart for Appwrite</span
>
<span>(appwrite/appwrite)</span> <span>(appwrite/appwrite)</span>
</div> </div>
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8"> <ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8">
@@ -199,7 +216,9 @@
</td> </td>
<td class="aw-table-line-cell"> <td class="aw-table-line-cell">
<div> <div>
<span class="aw-sub-body-500 aw-u-color-text-accent-click">Create a Helm Chart for Appwrite</span> <span class="aw-sub-body-500 aw-u-color-text-accent-click"
>Create a Helm Chart for Appwrite</span
>
<span>(appwrite/appwrite)</span> <span>(appwrite/appwrite)</span>
</div> </div>
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8"> <ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8">
@@ -221,7 +240,9 @@
</td> </td>
<td class="aw-table-line-cell"> <td class="aw-table-line-cell">
<div> <div>
<span class="aw-sub-body-500 aw-u-color-text-accent-click">Create a Helm Chart for Appwrite</span> <span class="aw-sub-body-500 aw-u-color-text-accent-click"
>Create a Helm Chart for Appwrite</span
>
<span>(appwrite/appwrite)</span> <span>(appwrite/appwrite)</span>
</div> </div>
<ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8"> <ul class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-8">
@@ -247,41 +268,54 @@
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">
<section class="aw-container"> <section class="aw-container">
<h4 class="aw-label aw-u-color-text-primary">Other ways to help</h4> <h4 class="aw-label aw-u-color-text-primary">Other ways to help</h4>
<ul class="grid-box u-gap-32 aw-u-gap-20-mobile u-margin-block-start-20" style="--grid-item-size:15rem"> <ul
class="grid-box u-gap-32 aw-u-gap-20-mobile u-margin-block-start-20"
style="--grid-item-size:15rem"
>
<li> <li>
<div class="aw-card is-normal u-flex-vertical aw-u-gap-6"> <div class="aw-card is-normal u-flex-vertical aw-u-gap-6">
<div class="aw-sub-body-500 aw-u-color-text-primary">Blogging & Speaking</div> <div class="aw-sub-body-500 aw-u-color-text-primary">Create content</div>
<div class="aw-sub-body-400">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </div> <div class="aw-sub-body-400">
Help others discover Appwrite with videos and blogs.
</div>
</div> </div>
</li> </li>
<li> <li>
<div class="aw-card is-normal u-flex-vertical aw-u-gap-6"> <div class="aw-card is-normal u-flex-vertical aw-u-gap-6">
<div class="aw-sub-body-500 aw-u-color-text-primary">Presenting at Meetups</div> <div class="aw-sub-body-500 aw-u-color-text-primary">Present at meetups</div>
<div class="aw-sub-body-400">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </div> <div class="aw-sub-body-400">
Share your experience and represent Appwrite in public.
</div>
</div> </div>
</li> </li>
<li> <li>
<div class="aw-card is-normal u-flex-vertical aw-u-gap-6"> <div class="aw-card is-normal u-flex-vertical aw-u-gap-6">
<div class="aw-sub-body-500 aw-u-color-text-primary">Reporting Bugs</div> <div class="aw-sub-body-500 aw-u-color-text-primary">Report bugs</div>
<div class="aw-sub-body-400">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </div> <div class="aw-sub-body-400">Find bugs and submit PRs to fix them.</div>
</div> </div>
</li> </li>
<li> <li>
<div class="aw-card is-normal u-flex-vertical aw-u-gap-6"> <div class="aw-card is-normal u-flex-vertical aw-u-gap-6">
<div class="aw-sub-body-500 aw-u-color-text-primary">Submitting New Ideas</div> <div class="aw-sub-body-500 aw-u-color-text-primary">Submit new ideas</div>
<div class="aw-sub-body-400">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </div> <div class="aw-sub-body-400">
Suggest features, integrations, or SDKs for our roadmap.
</div>
</div> </div>
</li> </li>
<li> <li>
<div class="aw-card is-normal u-flex-vertical aw-u-gap-6"> <div class="aw-card is-normal u-flex-vertical aw-u-gap-6">
<div class="aw-sub-body-500 aw-u-color-text-primary">Improving documentation</div> <div class="aw-sub-body-500 aw-u-color-text-primary">Improve documentation</div>
<div class="aw-sub-body-400">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </div> <div class="aw-sub-body-400">
Find improvements in our docs and improve accessibility.
</div>
</div> </div>
</li> </li>
<li> <li>
<div class="aw-card is-normal u-flex-vertical aw-u-gap-6"> <div class="aw-card is-normal u-flex-vertical aw-u-gap-6">
<div class="aw-sub-body-500 aw-u-color-text-primary">Helping other contributors</div> <div class="aw-sub-body-500 aw-u-color-text-primary">Helping others</div>
<div class="aw-sub-body-400">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </div> <div class="aw-sub-body-400">
Support community members with their projects and contributions.
</div>
</div> </div>
</li> </li>
</ul> </ul>
@@ -289,155 +323,164 @@
</div> </div>
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">
<section class="aw-container aw-u-sep-block-start aw-u-padding-block-start-64"> <section class="aw-container aw-u-sep-block-start aw-u-padding-block-start-64">
<div class="u-flex u-gap-16 u-main-space-between"> <Carousel>
<h4 class="aw-label aw-u-color-text-primary">Upcoming Events</h4> <svelte:fragment slot="header">
<div class="u-flex u-gap-12"> <h4 class="aw-label aw-u-color-text-primary">Upcoming Events</h4>
<button class="aw-icon-button" aria-label="Move carousel backward" disabled> </svelte:fragment>
<span class="aw-icon-arrow-left" aria-hidden="true"></span> <li>
</button> <a class="aw-grid-articles-item" href="/discord" target="_blank">
<button class="aw-icon-button" aria-label="Move carousel forward"> <div class="aw-grid-articles-item-image">
<span class="aw-icon-arrow-right" aria-hidden="true"></span> <img
</button> src="/images/community/events/office-hours.png"
</div> class="aw-u-media-ratio-16-9"
</div> alt=""
/>
<div class="aw-grid-articles-scroll"> </div>
<ul class="aw-grid-articles aw-u-gap-32 u-margin-block-start-32"> <div class="aw-grid-articles-item-content is-no-gap">
<li> <ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep">
<a class="aw-grid-articles-item" href="/discord" target="_blank"> <li class="u-flex u-cross-baseline u-gap-4">
<div class="aw-grid-articles-item-image"> <span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true" />
<img src="/images/community/events/office-hours.png" class="aw-u-media-ratio-16-9" alt=""> <time class="">Sep 28th, 2023</time>
</div> </li>
<div class="aw-grid-articles-item-content is-no-gap"> <li class="u-flex u-cross-baseline u-gap-4">
<ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep"> <span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true" />
<li class="u-flex u-cross-baseline u-gap-4"> <span class="">Discord</span>
<span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true"></span> </li>
<time class="">Sep 28th, 2023</time> </ul>
</li> <h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4">
<li class="u-flex u-cross-baseline u-gap-4"> Office hours
<span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true"></span> </h5>
<span class="">Discord</span> <p class="aw-sub-body-500">
</li> Join us for an exciting hour of technical conversations around Appwrite.
</ul> </p>
<h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4"> <div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
Office hours <button class="aw-button is-secondary">
</h5> <span>View event</span>
<p class="aw-sub-body-500"> </button>
Join us for an exciting hour of technical conversations around Appwrite. <!-- <button class="aw-button is-text">
</p>
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<button class="aw-button is-secondary">
<span>View event</span>
</button>
<!-- <button class="aw-button is-text">
<span>Add to calendar</span> <span>Add to calendar</span>
</button> --> </button> -->
</div>
</div> </div>
</a> </div>
</li> </a>
<li> </li>
<a class="aw-grid-articles-item" href="https://www.twitch.tv/wesscope" target="_blank"> <li>
<div class="aw-grid-articles-item-image"> <a
<img src="/images/community/events/live-coding.png" class="aw-u-media-ratio-16-9" alt=""> class="aw-grid-articles-item"
</div> href="https://www.twitch.tv/wesscope"
<div class="aw-grid-articles-item-content is-no-gap"> target="_blank"
<ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep"> >
<li class="u-flex u-cross-baseline u-gap-4"> <div class="aw-grid-articles-item-image">
<span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true"></span> <img
<time class="">Sep 28th, 2023</time> src="/images/community/events/live-coding.png"
</li> class="aw-u-media-ratio-16-9"
<li class="u-flex u-cross-baseline u-gap-4"> alt=""
<span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true"></span> />
<span class="">Twitch</span> </div>
</li> <div class="aw-grid-articles-item-content is-no-gap">
</ul> <ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep">
<h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4"> <li class="u-flex u-cross-baseline u-gap-4">
Live coding with Wess <span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true" />
</h5> <time class="">Sep 28th, 2023</time>
<p class="aw-sub-body-500"> </li>
Pluck is going mobile. Join us in building Pluck.io's Flutter app. <li class="u-flex u-cross-baseline u-gap-4">
</p> <span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true" />
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16"> <span class="">Twitch</span>
<button class="aw-button is-secondary"> </li>
<span>View event</span> </ul>
</button> <h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4">
<!-- <button class="aw-button is-text"> Live coding with Wess
</h5>
<p class="aw-sub-body-500">
Pluck is going mobile. Join us in building Pluck.io's Flutter app.
</p>
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<button class="aw-button is-secondary">
<span>View event</span>
</button>
<!-- <button class="aw-button is-text">
<span>Add to calendar</span> <span>Add to calendar</span>
</button> --> </button> -->
</div>
</div> </div>
</a> </div>
</li> </a>
<li> </li>
<a class="aw-grid-articles-item" href="https://lu.ma/hf-kickoff-blr" target="_blank"> <li>
<div class="aw-grid-articles-item-image"> <a class="aw-grid-articles-item" href="https://lu.ma/hf-kickoff-blr" target="_blank">
<img src="/images/community/events/hf-kickoff-bangalore.png" class="aw-u-media-ratio-16-9" alt="Hacktoberfest kickoff event"> <div class="aw-grid-articles-item-image">
</div> <img
<div class="aw-grid-articles-item-content is-no-gap"> src="/images/community/events/hf-kickoff-bangalore.png"
<ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep"> class="aw-u-media-ratio-16-9"
<li class="u-flex u-cross-baseline u-gap-4"> alt="Hacktoberfest kickoff event"
<span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true"></span> />
<time class="">Oct 1st, 2023</time> </div>
</li> <div class="aw-grid-articles-item-content is-no-gap">
<li class="u-flex u-cross-baseline u-gap-4"> <ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep">
<span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true"></span> <li class="u-flex u-cross-baseline u-gap-4">
<span class="">Bengaluru</span> <span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true" />
</li> <time class="">Oct 1st, 2023</time>
</ul> </li>
<h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4"> <li class="u-flex u-cross-baseline u-gap-4">
Hacktoberfest kickoff event <span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true" />
</h5> <span class="">Bengaluru</span>
<p class="aw-sub-body-500"> </li>
Join us for our Hacktoberfest kickoff event in Bengaluru. </ul>
</p> <h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4">
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16"> Hacktoberfest kickoff event
<button class="aw-button is-secondary"> </h5>
<span>View event</span> <p class="aw-sub-body-500">
</button> Join us for our Hacktoberfest kickoff event in Bengaluru.
<!-- <button class="aw-button is-text"> </p>
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<button class="aw-button is-secondary">
<span>View event</span>
</button>
<!-- <button class="aw-button is-text">
<span>Add to calendar</span> <span>Add to calendar</span>
</button> --> </button> -->
</div>
</div> </div>
</a> </div>
</li> </a>
<li> </li>
<a class="aw-grid-articles-item" href="https://hacktoberfest.com/"> <li>
<div class="aw-grid-articles-item-image"> <a class="aw-grid-articles-item" href="https://hacktoberfest.com/">
<img src="/images/community/events/oss-celebration.png" class="aw-u-media-ratio-16-9" alt="Hacktoberfest kickoff event"> <div class="aw-grid-articles-item-image">
</div> <img
<div class="aw-grid-articles-item-content is-no-gap"> src="/images/community/events/oss-celebration.png"
<ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep"> class="aw-u-media-ratio-16-9"
<li class="u-flex u-cross-baseline u-gap-4"> alt="Hacktoberfest kickoff event"
<span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true"></span> />
<time class="">Oct, 2023</time> </div>
</li> <div class="aw-grid-articles-item-content is-no-gap">
<li class="u-flex u-cross-baseline u-gap-4"> <ul class="u-flex u-flex-wrap aw-u-list-inline-dot-sep">
<span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true"></span> <li class="u-flex u-cross-baseline u-gap-4">
<span class="">Virtual</span> <span class="aw-icon-calendar aw-u-color-text-tertiary" aria-hidden="true" />
</li> <time class="">Oct, 2023</time>
</ul> </li>
<h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4"> <li class="u-flex u-cross-baseline u-gap-4">
Hacktoberfest 10 <span class="aw-icon-location aw-u-color-text-tertiary" aria-hidden="true" />
</h5> <span class="">Virtual</span>
<p class="aw-sub-body-500"> </li>
Join us for a month long celebration of open source in collaboration with DigitalOcean. </ul>
</p> <h5 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-4">
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16"> Hacktoberfest 10
<button class="aw-button is-secondary"> </h5>
<span>View event</span> <p class="aw-sub-body-500">
</button> Join us for a month long celebration of open source in collaboration with
<!-- <button class="aw-button is-text"> DigitalOcean.
</p>
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-16">
<button class="aw-button is-secondary">
<span>View event</span>
</button>
<!-- <button class="aw-button is-text">
<span>Add to calendar</span> <span>Add to calendar</span>
</button> --> </button> -->
</div>
</div> </div>
</a> </div>
</li> </a>
</ul> </li>
</div> </Carousel>
</section> </section>
</div> </div>
</div> </div>
@@ -448,47 +491,76 @@
<div class="aw-hero is-center"> <div class="aw-hero is-center">
<h2 class="aw-display aw-u-color-text-primary">Inspire and get inspired</h2> <h2 class="aw-display aw-u-color-text-primary">Inspire and get inspired</h2>
<p class="aw-description"> <p class="aw-description">
Visit our showcase website Built with Appwrite to find inspiration for your projects or to showcase what you have built. Join hundreds of developers. Visit our showcase website built with Appwrite to find inspiration for your projects
or to showcase what you have built.
</p> </p>
<a href="https://builtwith.appwrite.io" target="_blank" class="aw-button is-secondary aw-u-cross-child-center u-margin-block-start-16"> <a
href="https://builtwith.appwrite.io"
target="_blank"
class="aw-button is-secondary aw-u-cross-child-center u-margin-block-start-16"
>
<span>View all projects</span> <span>View all projects</span>
</a> </a>
</div> </div>
<ul class="aw-grid-3-desktop-1-mobile aw-u-margin-block-start-64"> <ul class="aw-grid-3-desktop-1-mobile aw-u-margin-block-start-64">
<li> <li>
<a class="aw-card is-white aw-u-flex-vertical u-gap-8" href="https://builtwith.appwrite.io/projects/6467cedd4502d0e29205/" target="_blank" style="--card-padding:0.5rem;"> <a
<div class="u-padding-12"> class="aw-card is-white aw-u-flex-vertical u-gap-8"
<h3 class="aw-main-body-500 aw-u-color-text-primary">Auth UI</h3> href="https://builtwith.appwrite.io/projects/6467cedd4502d0e29205/"
<p class="u-trim-2"> target="_blank"
Appwirte-powered authentication screens generator for any application. style="--card-padding:0.5rem;"
</p> >
</div> <div class="u-padding-12">
<img src="https://cloud.appwrite.io/v1/storage/buckets/thumbnails/files/64803bb4f34eb4b05ee3/preview?width=800&output=webp&project=builtWithAppwrite" <h3 class="aw-main-body-500 aw-u-color-text-primary">Auth UI</h3>
class="u-width-full-line aw-u-block-size-160 aw-u-media-cover" alt=""> <p class="u-trim-2">
</a> Appwirte-powered authentication screens generator for any application.
</li> </p>
</div>
<img
src="https://cloud.appwrite.io/v1/storage/buckets/thumbnails/files/64803bb4f34eb4b05ee3/preview?width=800&output=webp&project=builtWithAppwrite"
class="u-width-full-line aw-u-block-size-160 aw-u-media-cover"
alt=""
/>
</a>
</li>
<li> <li>
<a class="aw-card is-white aw-u-flex-vertical u-gap-8" href="https://builtwith.appwrite.io/projects/648bfe0c1d8d70602b0b/" target="_blank" style="--card-padding:0.5rem;"> <a
class="aw-card is-white aw-u-flex-vertical u-gap-8"
href="https://builtwith.appwrite.io/projects/648bfe0c1d8d70602b0b/"
target="_blank"
style="--card-padding:0.5rem;"
>
<div class="u-padding-12"> <div class="u-padding-12">
<h3 class="aw-main-body-500 aw-u-color-text-primary">Glitch</h3> <h3 class="aw-main-body-500 aw-u-color-text-primary">Glitch</h3>
<p class="u-trim-2"> <p class="u-trim-2">
Appwrite-powered collaboration Tool for streamlined team communication. Appwrite-powered collaboration Tool for streamlined team communication.
</p> </p>
</div> </div>
<img src="/images/community/projects/glitch.png" <img
class="u-width-full-line aw-u-block-size-160 aw-u-media-cover" alt=""> src="/images/community/projects/glitch.png"
class="u-width-full-line aw-u-block-size-160 aw-u-media-cover"
alt=""
/>
</a> </a>
</li> </li>
<li> <li>
<a class="aw-card is-white aw-u-flex-vertical u-gap-8" href="https://builtwith.appwrite.io/projects/648606ad9cd179190b28/" target="_blank" style="--card-padding:0.5rem;"> <a
class="aw-card is-white aw-u-flex-vertical u-gap-8"
href="https://builtwith.appwrite.io/projects/648606ad9cd179190b28/"
target="_blank"
style="--card-padding:0.5rem;"
>
<div class="u-padding-12"> <div class="u-padding-12">
<h3 class="aw-main-body-500 aw-u-color-text-primary">uCanEarn</h3> <h3 class="aw-main-body-500 aw-u-color-text-primary">uCanEarn</h3>
<p class="u-trim-2"> <p class="u-trim-2">
Appwrite-powered platform where you can sell your digital products online. Appwrite-powered platform where you can sell your digital products online.
</p> </p>
</div> </div>
<img src="/images/community/projects/ucanearn.png" <img
class="u-width-full-line aw-u-block-size-160 aw-u-media-cover" alt=""> src="/images/community/projects/ucanearn.png"
class="u-width-full-line aw-u-block-size-160 aw-u-media-cover"
alt=""
/>
</a> </a>
</li> </li>
</ul> </ul>
@@ -501,65 +573,75 @@
<div class="aw-grid-15-25-desktop aw-u-row-gap-48 aw-u-column-gap-96"> <div class="aw-grid-15-25-desktop aw-u-row-gap-48 aw-u-column-gap-96">
<div class="aw-hero is-align-start aw-u-max-width-380"> <div class="aw-hero is-align-start aw-u-max-width-380">
<div class="aw-display aw-u-color-text-primary">Visit the community</div> <div class="aw-display aw-u-color-text-primary">Visit the community</div>
<p class="aw-description">Discover more about Appwrite by visiting our community across platforms.</p> <p class="aw-description">
Discover Appwrite's community across platforms and join the fun.
</p>
</div> </div>
<ul class="aw-multi-columns-1"> <ul class="aw-multi-columns-1">
<li> <li>
<a href="/discord" target="_blank" <a
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical" href="/discord"
style="--card-padding:2rem" target="_blank"
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical"
style="--card-padding:2rem"
> >
<div class="u-flex-vertical u-main-space-between u-gap-32"> <div class="u-flex-vertical u-main-space-between u-gap-32">
<span <span
class="icon-discord aw-u-font-size-40" class="icon-discord aw-u-font-size-40"
aria-hidden="true" aria-hidden="true"
aria-label="Discord logo" aria-label="Discord logo"
/> />
</div> </div>
<div class="aw-title u-margin-block-start-auto">17K+ members</div> <div class="aw-title u-margin-block-start-auto">17K+ members</div>
</a> </a>
</li> </li>
<li> <li>
<a href="https://twitter.com/intent/follow?screen_name=appwrite" target="_blank" <a
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical" href="https://twitter.com/intent/follow?screen_name=appwrite"
style="--card-padding:2rem" target="_blank"
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical"
style="--card-padding:2rem"
> >
<div class="u-flex-vertical u-main-space-between u-gap-32"> <div class="u-flex-vertical u-main-space-between u-gap-32">
<span <span
class="aw-icon-x aw-u-font-size-40" class="aw-icon-x aw-u-font-size-40"
aria-hidden="true" aria-hidden="true"
aria-label="X logo" aria-label="X logo"
/> />
</div> </div>
<div class="aw-title u-margin-block-start-auto">125K+ followers</div> <div class="aw-title u-margin-block-start-auto">125K+ followers</div>
</a> </a>
</li> </li>
<li> <li>
<a href="https://github.com/appwrite/appwrite" target="_blank" <a
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical" href="https://github.com/appwrite/appwrite"
style="--card-padding:2rem" target="_blank"
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical"
style="--card-padding:2rem"
> >
<div class="u-flex-vertical u-main-space-between u-gap-32"> <div class="u-flex-vertical u-main-space-between u-gap-32">
<span <span
class="icon-github aw-u-font-size-40" class="icon-github aw-u-font-size-40"
aria-hidden="true" aria-hidden="true"
aria-label="GitHub logo" aria-label="GitHub logo"
/> />
</div> </div>
<div class="aw-title u-margin-block-start-auto">33K+ stargazers</div> <div class="aw-title u-margin-block-start-auto">33K+ stargazers</div>
</a> </a>
</li> </li>
<li> <li>
<a href="https://www.youtube.com/c/appwrite?sub_confirmation=1" target="_blank" <a
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical" href="https://www.youtube.com/c/appwrite?sub_confirmation=1"
style="--card-padding:2rem" target="_blank"
class="aw-card is-white aw-u-min-block-size-320 u-flex-vertical"
style="--card-padding:2rem"
> >
<div class="u-flex-vertical u-main-space-between u-gap-32"> <div class="u-flex-vertical u-main-space-between u-gap-32">
<span <span
class="icon-youtube aw-u-font-size-40" class="icon-youtube aw-u-font-size-40"
aria-hidden="true" aria-hidden="true"
aria-label="Youtube logo" aria-label="Youtube logo"
/> />
</div> </div>
<div class="aw-title u-margin-block-start-auto">3K+ subscribers</div> <div class="aw-title u-margin-block-start-auto">3K+ subscribers</div>
</a> </a>
@@ -571,17 +653,17 @@
</div> </div>
<div class="aw-big-padding-section-level-1 u-padding-0"> <div class="aw-big-padding-section-level-1 u-padding-0">
<div class="aw-big-padding-section-level-2"> <div class="aw-big-padding-section-level-2">
<div class="aw-container"> <div class="aw-container">
<div class="aw-hero is-center aw-u-max-width-800"> <div class="aw-hero is-center aw-u-max-width-800">
<h3 class="aw-display aw-u-color-text-primary">Appwrite insights</h3> <h3 class="aw-display aw-u-color-text-primary">Appwrite insights</h3>
<p class="aw-main-body-400">Sign up to our blog and get the latest insights from Appwrite. Learn more about engineering, product design, building community, and tips & tricks for using Appwrite.</p> <p class="aw-main-body-400">
Sign up to our blog and get the latest insights from Appwrite. Learn more about
engineering, product design, building community, and tips & tricks for using Appwrite.
</p>
</div> </div>
<div <div
class="aw-subscribe-input aw-input-text is-reset-input-inside u-width-full-line aw-u-max-width-380 u-margin-inline-auto u-margin-block-start-32" class="aw-subscribe-input aw-input-text is-reset-input-inside u-width-full-line aw-u-max-width-380 u-margin-inline-auto u-margin-block-start-32"
> >
<input type="email" placeholder="Enter your email" /> <input type="email" placeholder="Enter your email" />
<button class="aw-button">Sign up</button> <button class="aw-button">Sign up</button>
@@ -589,9 +671,7 @@
</div> </div>
</div> </div>
<div <div class="aw-big-padding-section-level-2 is-margin-replace-padding u-position-relative">
class="aw-big-padding-section-level-2 is-margin-replace-padding u-position-relative"
>
<div class="aw-container"> <div class="aw-container">
<PreFooter /> <PreFooter />
<FooterNav /> <FooterNav />

View File

@@ -505,7 +505,7 @@
<div class="aw-container"> <div class="aw-container">
<div class="aw-hero aw-u-max-width-380"> <div class="aw-hero aw-u-max-width-380">
<h3 class="aw-display aw-u-color-text-primary">Join the team</h3> <h3 class="aw-display aw-u-color-text-primary">Join the team</h3>
<p>Find your next career at Appwrite and join a team of remote workers.</p> <p class="aw-u-color-text-primary aw-u-opacity-64">Find your next career at Appwrite and join a team of remote workers.</p>
<button class="aw-button is-transparent u-cross-child-center u-margin-block-start-16"> <button class="aw-button is-transparent u-cross-child-center u-margin-block-start-16">
<span>Careers</span> <span>Careers</span>
</button> </button>

View File

@@ -44,7 +44,10 @@
<Spline let:fallback let:viewer> <Spline let:fallback let:viewer>
<div <div
class="u-position-absolute aw-is-not-mobile" class="u-position-absolute aw-is-not-mobile"
style="inline-size:512px; block-size: 512px; inset-block-start:24rem; inset-inline-start:calc(100% - 500px)" style:inline-size="512px"
style:block-size="512px"
style:inset-block-start="32rem"
style:left="calc(50% - 256px + 500px)"
> >
<img <img
src="/images/animations/tech.png" src="/images/animations/tech.png"
@@ -68,70 +71,178 @@
Run on any provider or through Appwrite Cloud Run on any provider or through Appwrite Cloud
</h1> </h1>
<p class="aw-description u-max-width-600"> <p class="aw-description u-max-width-600">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin in ultrices lacus. Start building today by creating an account on <a href="https://cloud.appwrite.io/" rel="noopener noreferrer" target="_blank">Appwrite Cloud</a>
or <a href="/docs/advanced/self-hosting" rel="noopener noreferrer" target="_blank">self-host</a>.
</p> </p>
</section> </section>
<section class="aw-hero is-align-start"> <section class="aw-hero is-align-start">
<h2 class="aw-title aw-u-color-text-primary u-max-width-600"> <h2 class="aw-title aw-u-color-text-primary u-max-width-600">
Get started quickly with your preferred technology Get started with your technologies
</h2> </h2>
<p class="aw-description u-max-width-600"> <p class="aw-description u-max-width-600">
Start building with your preferred web, mobile, and native frameworks by following a quick Follow a quick start guide on your web, mobile, and native frameworks.
start guide.
</p> </p>
<ul class="u-flex u-gap-16 aw-u-margin-block-32-mobile aw-u-margin-block-40-not-mobile"> <ul class="u-flex u-gap-16 aw-u-margin-block-32-mobile aw-u-margin-block-40-not-mobile">
<li> <li>
<a href="/docs/quick-starts/flutter" class="aw-box-icon"> <a href="/docs/quick-starts/flutter" class="aw-box-icon">
<img src="/images/platforms/dark/flutter.svg" alt="Flutter logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/flutter.svg" alt="Flutter logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/flutter.svg"
alt="Flutter logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/flutter.svg"
alt="Flutter logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/nextjs" class="aw-box-icon"> <a href="/docs/quick-starts/nextjs" class="aw-box-icon">
<img src="/images/platforms/dark/nextjs.svg" alt="Next.js logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/nextjs.svg" alt="Next.js logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/nextjs.svg"
alt="Next.js logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/nextjs.svg"
alt="Next.js logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/react" class="aw-box-icon"> <a href="/docs/quick-starts/react" class="aw-box-icon">
<img src="/images/platforms/dark/react.svg" alt="React logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/react.svg" alt="React logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/react.svg"
alt="React logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/react.svg"
alt="React logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/sveltekit" class="aw-box-icon"> <a href="/docs/quick-starts/sveltekit" class="aw-box-icon">
<img src="/images/platforms/dark/svelte.svg" alt="Svelte logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/svelte.svg" alt="Svelte logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/svelte.svg"
alt="Svelte logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/svelte.svg"
alt="Svelte logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/nuxt" class="aw-box-icon"> <a href="/docs/quick-starts/nuxt" class="aw-box-icon">
<img src="/images/platforms/dark/nuxt.svg" alt="Nuxt logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/nuxt.svg" alt="Nuxt logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/nuxt.svg"
alt="Nuxt logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/nuxt.svg"
alt="Nuxt logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/vue" class="aw-box-icon"> <a href="/docs/quick-starts/vue" class="aw-box-icon">
<img src="/images/platforms/dark/vue.svg" alt="Vue logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/vue.svg" alt="Vue logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/vue.svg"
alt="Vue logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/vue.svg"
alt="Vue logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/angular" class="aw-box-icon"> <a href="/docs/quick-starts/angular" class="aw-box-icon">
<img src="/images/platforms/dark/angular.svg" alt="Angular logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/angular.svg" alt="Angular logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/angular.svg"
alt="Angular logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/angular.svg"
alt="Angular logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/apple" class="aw-box-icon"> <a href="/docs/quick-starts/apple" class="aw-box-icon">
<img src="/images/platforms/dark/apple.svg" alt="Apple logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/apple.svg" alt="Apple logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/apple.svg"
alt="Apple logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/apple.svg"
alt="Apple logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
<li> <li>
<a href="/docs/quick-starts/android" class="aw-box-icon"> <a href="/docs/quick-starts/android" class="aw-box-icon">
<img src="/images/platforms/dark/android.svg" alt="Android logo" class="u-only-dark" width="32" height="32" /> <img
<img src="/images/platforms/android.svg" alt="Android logo" class="u-only-light" width="32" height="32" /> src="/images/platforms/dark/android.svg"
alt="Android logo"
class="u-only-dark"
width="32"
height="32"
/>
<img
src="/images/platforms/android.svg"
alt="Android logo"
class="u-only-light"
width="32"
height="32"
/>
</a> </a>
</li> </li>
</ul> </ul>
@@ -145,8 +256,7 @@
<div> <div>
<h2 class="aw-title aw-u-color-text-primary u-max-width-600">Show me some code</h2> <h2 class="aw-title aw-u-color-text-primary u-max-width-600">Show me some code</h2>
<p class="aw-description u-max-width-600"> <p class="aw-description u-max-width-600">
Talk is cheap, where's the code? If you'd rather see some examples, we've got you If you learn best from code examples, follow one of our tutorials.
covered. Clone a template to get started.
</p> </p>
</div> </div>
</svelte:fragment> </svelte:fragment>
@@ -290,7 +400,7 @@
</Carousel> </Carousel>
</section> </section>
<section class="aw-hero is-align-start is-no-max-width"> <section class="aw-hero is-align-start is-no-max-width">
<h2 class="aw-title aw-u-color-text-primary u-max-width-600">Show me some code</h2> <h2 class="aw-title aw-u-color-text-primary u-max-width-600">Explore capabilities</h2>
<p class="aw-description u-max-width-600"> <p class="aw-description u-max-width-600">
All the core functionalities you need with a scalable and flexible API. Explore Appwrite's All the core functionalities you need with a scalable and flexible API. Explore Appwrite's
product offerings. product offerings.
@@ -299,8 +409,20 @@
<ul class="aw-grid-row-4 aw-grid-row-4-m-1"> <ul class="aw-grid-row-4 aw-grid-row-4-m-1">
<li> <li>
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<img src="/images/icons/illustrated/dark/auth.png" alt="" class="u-only-dark" width="48" height="48" /> <img
<img src="/images/icons/illustrated/light/auth.png" alt="" class="u-only-light" width="48" height="48" /> src="/images/icons/illustrated/dark/auth.png"
alt=""
class="u-only-dark"
width="48"
height="48"
/>
<img
src="/images/icons/illustrated/light/auth.png"
alt=""
class="u-only-light"
width="48"
height="48"
/>
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">Auth</h4> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">Auth</h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Sign in users with multiple OAuth providers. Sign in users with multiple OAuth providers.
@@ -309,20 +431,44 @@
</li> </li>
<li> <li>
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<img src="/images/icons/illustrated/dark/databases.png" alt="" class="u-only-dark" width="48" height="48" /> <img
<img src="/images/icons/illustrated/light/databases.png" alt="" class="u-only-light" width="48" height="48" /> src="/images/icons/illustrated/dark/databases.png"
alt=""
class="u-only-dark"
width="48"
height="48"
/>
<img
src="/images/icons/illustrated/light/databases.png"
alt=""
class="u-only-light"
width="48"
height="48"
/>
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8"> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">
Databases Databases
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Store your application and users' data. Store your application and user data.
</p> </p>
</div> </div>
</li> </li>
<li> <li>
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<img src="/images/icons/illustrated/dark/functions.png" alt="" class="u-only-dark" width="48" height="48" /> <img
<img src="/images/icons/illustrated/light/functions.png" alt="" class="u-only-light" width="48" height="48" /> src="/images/icons/illustrated/dark/functions.png"
alt=""
class="u-only-dark"
width="48"
height="48"
/>
<img
src="/images/icons/illustrated/light/functions.png"
alt=""
class="u-only-light"
width="48"
height="48"
/>
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8"> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">
Functions Functions
</h4> </h4>
@@ -333,8 +479,20 @@
</li> </li>
<li> <li>
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<img src="/images/icons/illustrated/dark/storage.png" alt="" class="u-only-dark" width="48" height="48" /> <img
<img src="/images/icons/illustrated/light/storage.png" alt="" class="u-only-light" width="48" height="48" /> src="/images/icons/illustrated/dark/storage.png"
alt=""
class="u-only-dark"
width="48"
height="48"
/>
<img
src="/images/icons/illustrated/light/storage.png"
alt=""
class="u-only-light"
width="48"
height="48"
/>
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8"> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">
Storage Storage
</h4> </h4>
@@ -345,24 +503,41 @@
</li> </li>
<li> <li>
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<img src="/images/icons/illustrated/dark/realtime.png" alt="" class="u-only-dark" width="48" height="48" /> <img
<img src="/images/icons/illustrated/light/realtime.png" alt="" class="u-only-light" width="48" height="48" /> src="/images/icons/illustrated/dark/realtime.png"
alt=""
class="u-only-dark"
width="48"
height="48"
/>
<img
src="/images/icons/illustrated/light/realtime.png"
alt=""
class="u-only-light"
width="48"
height="48"
/>
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8"> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">
Realtime Realtime
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Listen to any events on the server-side in realtime. Respond to server events in realtime.
</p> </p>
</div> </div>
</li> </li>
<li> <li>
<div class="aw-card is-full-color u-opacity-20"> <div class="aw-card is-full-color u-opacity-20">
<img src="/images/icons/illustrated/dark/messaging.png" alt="" width="48" height="48" /> <img
src="/images/icons/illustrated/dark/messaging.png"
alt=""
width="48"
height="48"
/>
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8"> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">
Messaging Messaging
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Send email, SMS, push notification and chat messages to your users. Coming soon.
</p> </p>
</div> </div>
</li> </li>
@@ -381,7 +556,7 @@
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">SDKs</h4> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">SDKs</h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Elit id et diam lectus egestas habitasse. Light-weight SDKs for your favorite platforms.
</p> </p>
</div> </div>
</li> </li>
@@ -391,7 +566,7 @@
REST API REST API
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Elit id et diam lectus egestas habitasse. Integrate with HTTP requests without the needing an SDK
</p> </p>
</div> </div>
</li> </li>
@@ -401,7 +576,7 @@
GraphQL GraphQL
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Elit id et diam lectus egestas habitasse. Leverage GraphQL through our SDKs or integrate directly with REST endpoints.
</p> </p>
</div> </div>
</li> </li>
@@ -411,7 +586,7 @@
Realtime Realtime
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Elit id et diam lectus egestas habitasse. Respond to auth, databases, storage, and function events in realtime.
</p> </p>
</div> </div>
</li> </li>
@@ -421,17 +596,17 @@
<section class="aw-hero is-align-start is-no-max-width"> <section class="aw-hero is-align-start is-no-max-width">
<h2 class="aw-title aw-u-color-text-primary u-max-width-600">Migrate to Appwrite</h2> <h2 class="aw-title aw-u-color-text-primary u-max-width-600">Migrate to Appwrite</h2>
<p class="aw-description u-max-width-600"> <p class="aw-description u-max-width-600">
Lorem ipsum dolor sit amet consectetur. Orci netus est urna dictum eleifend diam. Own your data with automatic data migrations.
</p> </p>
<div class="u-margin-block-start-24"> <div class="u-margin-block-start-24">
<ul class="aw-grid-row-4"> <ul class="aw-grid-row-4">
<li> <li>
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8"> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">
Self hosted Self-hosted
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Move data from self-hosted to Appwrite Cloud.
</p> </p>
</div> </div>
</li> </li>
@@ -441,7 +616,7 @@
Firebase Firebase
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Migrate users and data from Firebase to Appwrite.
</p> </p>
</div> </div>
</li> </li>
@@ -451,7 +626,7 @@
Supabase Supabase
</h4> </h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Migrate users and data from Supabase to Appwrite.
</p> </p>
</div> </div>
</li> </li>
@@ -459,7 +634,7 @@
<div class="aw-card is-full-color"> <div class="aw-card is-full-color">
<h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">Nhost</h4> <h4 class="aw-sub-body-500 aw-u-color-text-primary u-margin-block-start-8">Nhost</h4>
<p class="aw-sub-body-400 u-margin-block-start-4"> <p class="aw-sub-body-400 u-margin-block-start-4">
Lorem ipsum dolor sit amet consectetur. Migrate users and data from NHost to Appwrite.
</p> </p>
</div> </div>
</li> </li>

View File

@@ -27,7 +27,8 @@
{ {
label: 'References', label: 'References',
href: '/docs/references', href: '/docs/references',
icon: 'icon-document' icon: 'icon-document',
isParent: true
} }
] ]
}, },
@@ -37,22 +38,26 @@
{ {
label: 'Auth', label: 'Auth',
href: '/docs/products/auth', href: '/docs/products/auth',
icon: 'icon-user-group' icon: 'icon-user-group',
isParent: true
}, },
{ {
label: 'Databases', label: 'Databases',
href: '/docs/products/databases', href: '/docs/products/databases',
icon: 'icon-database' icon: 'icon-database',
isParent: true
}, },
{ {
label: 'Functions', label: 'Functions',
href: '/docs/products/functions', href: '/docs/products/functions',
icon: 'icon-lightning-bolt' icon: 'icon-lightning-bolt',
isParent: true
}, },
{ {
label: 'Storage', label: 'Storage',
href: '/docs/products/storage', href: '/docs/products/storage',
icon: 'icon-folder' icon: 'icon-folder',
isParent: true
} }
] ]
}, },
@@ -82,7 +87,8 @@
{ {
label: 'Command Line', label: 'Command Line',
href: '/docs/tooling/command-line/installation', href: '/docs/tooling/command-line/installation',
icon: 'icon-terminal' icon: 'icon-terminal',
isParent: true
}, },
{ {
label: 'Assistant', label: 'Assistant',
@@ -97,17 +103,20 @@
{ {
label: 'Platform', label: 'Platform',
href: '/docs/advanced/platform', href: '/docs/advanced/platform',
icon: 'icon-play' icon: 'icon-play',
isParent: true
}, },
{ {
label: 'Migrations', label: 'Migrations',
href: '/docs/advanced/migrations', href: '/docs/advanced/migrations',
icon: 'icon-refresh' icon: 'icon-refresh',
isParent: true
}, },
{ {
label: 'Self-hosting', label: 'Self-hosting',
href: '/docs/advanced/self-hosting/installation', href: '/docs/advanced/self-hosting',
icon: 'icon-server' icon: 'icon-server',
isParent: true
} }
] ]
} }

View File

@@ -49,15 +49,18 @@ To begin migrating to Appwrite, follow these steps.
1. Click on the **Create Migration** button and select **Firebase** as your source. 1. Click on the **Create Migration** button and select **Firebase** as your source.
1. Upload the JSON file to Appwrite and follow the migration wizard to select which resources you need to migrate. 1. Upload the JSON file to Appwrite and follow the migration wizard to select which resources you need to migrate. Finally click **Start migration** to begin the migration process.
1. Add the platforms for your [Web](#), [Flutter](#), [Android](#), and [iOS](#) apps. Appwrite will reject requests from unknown web, Flutter, and mobile apps to protect from malicious attacks. You app **must be added as a platform** for Appwrite to accept requests. {% /section %}
{% section #next-steps step=4 title="Next steps" %}
1. In your Appwrite Console, navigate to **Overview** > **Integrations** > **Platforms**, add the platforms for your Web, Flutter, Android, and iOS apps. Appwrite will reject requests from unknown web, Flutter, and mobile apps to protect from malicious attacks. You app **must be added as a platform** for Appwrite to accept requests.
1. Remember to [add appropriate permissions](/docs/advanced/platform/permissions) to the migrated resources to protect user data and privacy. 1. Remember to [add appropriate permissions](/docs/advanced/platform/permissions) to the migrated resources to protect user data and privacy.
1. Migrate functions manually, by [pick a runtime](#) and [learn to develop Appwrite Functions](#). 1. Migrate functions manually, by [pick a runtime](/docs/products/functions/runtimes) and [learn to develop Appwrite Functions](/docs/products/functions/development).
1. Explore Appwrite's unique feature by exploring the [TODO] 1. Explore Appwrite's unique features by exploring the rest of the [Appwrite Documentation](/docs).
{% /section %} {% /section %}

View File

@@ -41,13 +41,13 @@ Before migrating to Appwrite make sure you've read the [migration overview](/doc
{% section #next-steps step=3 title="Next steps" %} {% section #next-steps step=3 title="Next steps" %}
1. Add the platforms for your [Web](#), [Flutter](#), [Android](#), and [iOS](#) apps. Appwrite will reject requests from unknown web, Flutter, and mobile apps to protect from malicious attacks. You app **must be added as a platform** for Appwrite to accept requests. 1. In your Appwrite Console, navigate to **Overview** > **Integrations** > **Platforms**, add the platforms for your Web, Flutter, Android, and iOS apps. Appwrite will reject requests from unknown web, Flutter, and mobile apps to protect from malicious attacks. You app **must be added as a platform** for Appwrite to accept requests.
1. Remember to [add appropriate permissions](/docs/advanced/platform/permissions) to the migrated resources to protect user data and privacy. 1. Remember to [add appropriate permissions](/docs/advanced/platform/permissions) to the migrated resources to protect user data and privacy.
1. Migrate functions manually, by [pick a runtime](#) and [learn to develop Appwrite Functions](#). 1. Migrate functions manually, by [pick a runtime](/docs/products/functions/runtimes) and [learn to develop Appwrite Functions](/docs/products/functions/development).
1. Explore Appwrite's unique feature by exploring the [TODO] 1. Explore Appwrite's unique features by exploring the rest of the [Appwrite Documentation](/docs).
{% /section %} {% /section %}

View File

@@ -40,6 +40,7 @@ To begin migrating to self-hosted, make sure to read the [migration overview](/d
1. Click **Start Migration** to start the migration process. You do not need to keep the Appwrite Console open through the process. 1. Click **Start Migration** to start the migration process. You do not need to keep the Appwrite Console open through the process.
> Keep in mind: Your self-hosted instance will generate an API Key in the background to pass to Appwrite Cloud. You can revoke this key after the migration process is complete. {% info title="Keep in mind" %}
Your self-hosted instance will generate an API Key in the background to pass to Appwrite Cloud. You can revoke this key after the migration process is complete.
{% /info %}
{% /section %} {% /section %}

View File

@@ -43,13 +43,13 @@ Before migrating to Appwrite make sure you've read the [migration overview](/doc
{% section #next-steps step=3 title="Next steps" %} {% section #next-steps step=3 title="Next steps" %}
1. Add the platforms for your [Web](#), [Flutter](#), [Android](#), and [iOS](#) apps. Appwrite will reject requests from unknown web, Flutter, and mobile apps to protect from malicious attacks. You app **must be added as a platform** for Appwrite to accept requests. 1. In your Appwrite Console, navigate to **Overview** > **Integrations** > **Platforms**, add the platforms for your Web, Flutter, Android, and iOS apps. Appwrite will reject requests from unknown web, Flutter, and mobile apps to protect from malicious attacks. You app **must be added as a platform** for Appwrite to accept requests.
1. Remember to [add appropriate permissions](/docs/advanced/platform/permissions) to the migrated resources to protect user data and privacy. 1. Remember to [add appropriate permissions](/docs/advanced/platform/permissions) to the migrated resources to protect user data and privacy.
1. Migrate functions manually, by [pick a runtime](#) and [learn to develop Appwrite Functions](#). 1. Migrate functions manually, by [pick a runtime](/docs/products/functions/runtimes) and [learn to develop Appwrite Functions](/docs/products/functions/development).
1. Explore Appwrite's unique feature by exploring the [TODO] 1. Explore Appwrite's unique features by exploring the rest of the [Appwrite Documentation](/docs).
{% /section %} {% /section %}

View File

@@ -18,24 +18,25 @@
] ]
}, },
{ {
label: 'Guides', label: 'Integration',
items: [ items: [
{
label: 'API keys',
href: '/docs/advanced/platform/api-keys'
},
{
label: 'Custom domains',
href: '/docs/advanced/platform/custom-domains'
},
{ {
label: 'Events', label: 'Events',
href: '/docs/advanced/platform/events' href: '/docs/advanced/platform/events'
}, },
{ {
label: 'Response codes', label: 'Webhooks',
href: '/docs/advanced/platform/response-codes' href: '/docs/advanced/platform/webhooks'
}, },
{
label: 'Response codes',
href: '/docs/advanced/platform/response-codes',
}
]
},
{
label: 'Access control',
items: [
{ {
label: 'Permissions', label: 'Permissions',
href: '/docs/advanced/platform/permissions' href: '/docs/advanced/platform/permissions'
@@ -45,11 +46,24 @@
href: '/docs/advanced/platform/rate-limits' href: '/docs/advanced/platform/rate-limits'
}, },
{ {
label: 'Webhooks', label: 'API keys',
href: '/docs/advanced/platform/webhooks' href: '/docs/advanced/platform/api-keys'
} },
] ]
} },
{
label: 'Configuration',
items: [
{
label: 'Custom domains',
href: '/docs/advanced/platform/custom-domains'
},
{
label: 'Email and SMS templates',
href: '/docs/advanced/platform/message-templates'
},
]
},
]; ];
</script> </script>

View File

@@ -7,26 +7,3 @@ description: Description for SEO.
Appwrite is a development platform designed to adapt your unique use cases. Appwrite is a development platform designed to adapt your unique use cases.
Appwrite provides features that help you maintain, scale, and integrate Appwrite with other platforms. Appwrite provides features that help you maintain, scale, and integrate Appwrite with other platforms.
## API keys {% #api-keys %}
[Learn more about API keys {% icon icon="cheveron-right" /%}](#)
## Custom domains {% #custom-domains %}
[Learn more about custom domains {% icon icon="cheveron-right" /%}](#)
## Events {% #events %}
[Learn more about events {% icon icon="cheveron-right" /%}](#)
## Response codes {% #response-codes %}
[Learn more about response codes {% icon icon="cheveron-right" /%}](#)
## Permissions {% #permissions %}
[Learn more about permissions {% icon icon="cheveron-right" /%}](#)
## Rate limits {% #rate-limits %}
[Learn more about permissions {% icon icon="cheveron-right" /%}](#)

View File

@@ -4,7 +4,7 @@ title: API keys
description: Placeholder SEO. description: Placeholder SEO.
--- ---
API keys are secrets used by Appwrite [Server SDKs](#) and the Appwrite CLI to prove their identity. API keys are secrets used by Appwrite [Server SDKs](/docs/sdks#server) and the Appwrite CLI to prove their identity.
What can be accessed each API key is restricted by [scopes](#scopes) instead of permissions. What can be accessed each API key is restricted by [scopes](#scopes) instead of permissions.
{% info title="Best practice" %} {% info title="Best practice" %}

View File

@@ -0,0 +1,196 @@
---
layout: article
title: Message templates
description: Placeholder SEO.
---
Appwrite uses emails to communicate with users to perform authentication and verification actions. Emails can be customized to fit your app's design and voice.
Each Appwrite project can have its own set of unique templates. Templates also support localization, so every template can be written in multiple languages and served depending on the configured locale.
## Custom SMTP server {% #smtp %}
Appwrite Cloud has a default SMTP server to get you started. This SMTP server sends generic emails and doesn't allow customizing SMTP templates. To use custom SMTP templates, you will need to configure your own SMTP server.
There are many third-party SMTP providers like SendGrid and Mailgun. Before proceeding, pick an SMTP provider, create an account, and obtain **Sender name**, **Sender email**, **Server host**, **Server port**, **Username**, and **Password**.
1. Navigate to your project's **Settings**.
2. Navigate to the **SMTP** tab.
3. Under **SMTP server**, toggle **Custom SMTP server**.
4. Input **Sender name**, **Sender email**, **Server host**, **Server port**, **Username**, and **Password** from your provider.
5. Click **Update**.
## Customize templates {% #customize %}
You can customize email templates for each of your projects in the Appwrite Console.
{% info title="Custom SMTP server required" %}
The built-in email service does not support custom email templates to prevent malicious templates.
Configure a [custom SMTP server](#smtp) to enable custom email templates.
{% /info %}
1. In your project, navigate to the **Auth** service.
2. Under the **Auth** service, navigate to the **Templates** tab.
3. Expand the email template you want to edit.
4. Select the **Template language**. You can have a different template for each language your app supports.
5. Update the email template fields and click **Update** to save your changes.
## Email templates {% #email-templates %}
You can customize the email templates for account verification, magic-url authentication, password resets, and user invites.
### Email template components {% #email-template-components %}
Each email template has the following components that you can customize.
| Component | Description |
|--------------|-----------------------------------------------------------------------------------------------------------------------|
| Sender name | Readers will see this as a display name of the sender. |
| Sender email | Readers will see this as a display email of the sender. This email must be authenticated on the SMTP provider you've configured, otherwise it will be delivered to the spam folder. This usually means the email must end with the same domain as your SMTP username. |
| Reply to | Readers will reply to this email address instead of the sender address. You can leave this field empty, and the sender email will be used automatically. |
| Subject | The title of the email. |
| Message | The body of the email in HTML format. You can find the variables available in the [Email Template Syntax](#email-template-syntax) section. |
### Email template syntax {% #email-template-syntax %}
Variables can be used in email templates to dynamically construct unique emails for each reader. These variables can only be used in the **Message** field of the email template.
| Variable | Description |
|------------|-----------------------------|
| `{{project}}` | The project name. |
| `{{team}}` | The project team's name. |
| `{{user}}` | The name of the user receiving the email. This variable is not available in the Magic URL template, as there might not be a user yet. |
| `{{redirect}}`| The URL for the user to complete the email template's action. |
### Email template syntax {% #email-template-examples %}
Here's an example of using these variables in a template.
```html
<!doctype html>
<html>
<head>
<style>
... your style here
</style>
</head>
<body style="direction: ltr">
<div style="max-width:650px; word-wrap: break-word; overflow-wrap: break-word;
word-break: break-all; margin:0 auto;">
<table style="margin-top: 32px">
<tr>
<td>
<h1>{{subject}}</h1>
</td>
</tr>
</table>
<table style="margin-top: 40px">
<tr>
<td>
<p>Hello </p>
<p>Follow this link to reset your {{project}} password.</p>
<a href="{{redirect}}" target="_blank">{{redirect}}</a>
<p><br />If you didn't ask to reset your password, you can ignore this message.</p>
<br />
<p>Thanks
<br />
{{project}} team</p>
</td>
</tr>
</table>
</div>
</body>
</html>
```
## Localization {% #localization %}
Each template can have multiple supported locales, displayed in different format and language. This can be configured under the **Template language** selector of each template.
You can send messages in different languages by setting the locale with `client.setLocale()` in the SDKs or the `X-Appwrite-Locale` HTTP header. [View here the list of available locales](https://github.com/appwrite/appwrite/blob/master/app/config/locale/codes.php).
For example, you can send an email verification in French.
{% multicode %}
```js
import { Client, Account } from "appwrite";
const client = new Client();
const account = new Account(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setLocale('fr') // Your locale
;
const promise = account.createVerification('https://example.com');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});
```
```dart
import 'package:appwrite/appwrite.dart';
void main() { // Init SDK
Client client = Client();
Account account = Account(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setLocale('fr') // Your locale
;
Future result = account.createVerification('https://example.com');
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setLocale('fr') // Your locale
val account = Account(client)
val response = account.createVerification('https://example.com')
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setLocale('fr') // Your locale
let account = Account(client)
let token = try await account.createVerification('https://example.com')
```
{% /multicode %}

View File

@@ -12,7 +12,7 @@ As the name suggests, read permission allows a user to read a resource, create a
All permissions can be granted to individuals or groups of users, entire teams, or only to team members with a specific role. Permission can also be granted based on authentication status, such as to all users, only authenticated users, or only guest users. All permissions can be granted to individuals or groups of users, entire teams, or only to team members with a specific role. Permission can also be granted based on authentication status, such as to all users, only authenticated users, or only guest users.
A project user can only grant permissions to a resource that they own. For example, if a user is trying to share a document with a team that they are not a member of, they will encounter a 401 not authorized error. If your app needs users to grant access to teams they're not a member of, you can create Appwrite Functions with a [Server SDK](#) to achieve this functionality. A project user can only grant permissions to a resource that they own. For example, if a user is trying to share a document with a team that they are not a member of, they will encounter a 401 not authorized error. If your app needs users to grant access to teams they're not a member of, you can create Appwrite Functions with a [Server SDK](/docs/sdks#server) to achieve this functionality.
## Appwrite Resource ## Appwrite Resource

View File

@@ -4,4 +4,188 @@ title: Response codes
description: Placeholder SEO. description: Placeholder SEO.
--- ---
TODO Appwrite uses conventional HTTP response codes to indicate the success or failure of an API request.
- Codes in the `2xx` range indicate success.
- Codes in the `4xx` range indicate an error caused by invalid request, usually caused by user error.
- Codes in the `5xx` range indicate an error with Appwrite, please check Docker container logs.
## Response codes {% #response-codes %}
| Code | Text | Description |
|------|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 200 | OK | Success! |
| 201 | Created | The requested resource has been created successfully. |
| 202 | Accepted | The requested change has been accepted for processing but has not been completed. |
| 204 | No Content | The server has successfully fulfilled the request and that there is no additional content to send in the response payload body. This status will usually return on successful delete operations. |
| 301 | Moved Permanently | The URL of the requested resource has been changed permanently. The new URL is given in the response. |
| 304 | Not Modified | There was no new data to return. |
| 400 | Bad Request | The request was invalid or cannot be otherwise served. An accompanying error message will explain further. Requests with wrong or invalid input will yield this response. |
| 401 | Unauthorized | Missing or incorrect authentication credentials can happen when the API key or user permission is not sufficient. |
| 403 | Forbidden | The request is understood, but it has been refused, or access is not allowed. An accompanying error message will explain why. Make sure to register your app in your project's dashboard platform list. |
| 404 | Not Found | The URI requested is invalid or the resource requested, such as a user, does not exist. |
| 409 | Conflict | This response is sent when a request conflicts with the current state of the server. This status code will usually appear when you're trying to create an already existing resource. |
| 413 | Payload Too Large | This indicates that the request entity is larger than limits defined by server. This status code will usually appear happen when uploading a file or function that is too large |
| 416 | Invalid Range | Invalid value in the range or content-range headers. Usually returned while uploading or downloading files using the range header but the provided range value is not valid. |
| 429 | Too Many Requests | Returned in when a request cannot be served due to the application's rate limit having been exhausted for the resource. See [Rate Limits](/docs/advanced/platform/rate-limits). |
| 500 | Internal Server Error | Something is broken. Contact our [team](/support), or raise a [GitHub issue](https://github.com/appwrite/appwrite/issues/new). |
| 501 | Not Implemented | The feature is not implemented. Usually returned when the project owner has disabled an auth method or an entire service. |
| 503 | Service Unavailable | The Appwrite servers are up but overloaded with requests. Try again later. |
| 504 | Gateway timeout | The Appwrite servers are up, but the request couldn't be serviced due to some failure within the stack. Try again later. |
## Error messages {% #error-messages %}
When the Appwrite APIs return error messages, it does so in JSON format. For example, an error might look like this:
```json
{
"message": "Invalid id: Parameter must be a valid number",
"type": "argument_invalid",
"code": 400
}
```
## Error types {% #error-types %}
Appwrite also passes convenient error types in addition to the HTTP response codes to help you get more fine-grained control over what went wrong and allowing you to display relevant error messages in your applications. Error types are convenient to identify the type of error that occurred.
For example, a `400` HTTP response code could indicate a Bad Request due to a variety of reasons, and error types can help you pinpoint the exact `400` error. Appwrite currently supports the following error types:
| Code | Type | Description |
| ---- | ---- | ----------- |
| 400 | general_mock | General errors thrown by the mock controller used for testing. |
| 400 | general_argument_invalid | The request contains one or more invalid arguments. Please refer to the endpoint documentation. |
| 400 | general_query_limit_exceeded | Query limit exceeded for the current attribute. Usage of more than 100 query values on a single attribute is prohibited. |
| 400 | general_query_invalid | The query's syntax is invalid. Please check the query and try again. |
| 400 | general_cursor_not_found | The cursor is invalid. This can happen if the item represented by the cursor has been deleted. |
| 400 | user_password_mismatch | Passwords do not match. Please check the password and confirm password. |
| 400 | password_recently_used | The password you are trying to use is similar to your previous password. For your security, please choose a different password and try again. |
| 400 | password_personal_data | The password you are trying to use contains references to your name, email, phone or userID. For your security, please choose a different password and try again. |
| 400 | user_phone_not_found | The current user does not have a phone number associated with their account. |
| 400 | user_missing_id | Missing ID from OAuth2 provider. |
| 400 | user_oauth2_bad_request | OAuth2 provider rejected the bad request. |
| 400 | storage_device_not_found | The requested storage device could not be found. |
| 400 | storage_file_empty | Empty file passed to the endpoint. |
| 400 | storage_file_type_unsupported | The given file extension is not supported. |
| 400 | storage_invalid_file_size | The file size is either not valid or exceeds the maximum allowed size. Please check the file or the value of the `_APP_STORAGE_LIMIT` environment variable. |
| 400 | storage_invalid_content_range | The content range is invalid. Please check the value of the `Content-Range` header. |
| 400 | storage_invalid_appwrite_id | The value for `x-appwrite-id` header is invalid. Please check the value of the `x-appwrite-id` header is a valid id and not `unique()`. |
| 400 | general_provider_failure | VCS (Version Control System) provider failed to process the request. We believe this is an error with the VCS provider. Try again, or contact support for more information. |
| 400 | build_not_ready | Build with the requested ID is building and not ready for execution. |
| 400 | build_in_progress | Build with the requested ID is already in progress. Please wait before you can retry. |
| 400 | collection_limit_exceeded | The maximum number of collections has been reached. |
| 400 | document_invalid_structure | The document structure is invalid. Please ensure the attributes match the collection definition. |
| 400 | document_missing_data | The document data is missing. Try again with document data populated. |
| 400 | document_missing_payload | The document data and permissions are missing. You must provide either document data or permissions to be updated. |
| 400 | attribute_unknown | The attribute required for the index could not be found. Please confirm all your attributes are in the available state. |
| 400 | attribute_not_available | The requested attribute is not yet available. Please try again later. |
| 400 | attribute_format_unsupported | The requested attribute format is not supported. |
| 400 | attribute_default_unsupported | Default values cannot be set for array or required attributes. |
| 400 | attribute_limit_exceeded | The maximum number of attributes has been reached. |
| 400 | attribute_value_invalid | The attribute value is invalid. Please check the type, range and value of the attribute. |
| 400 | attribute_type_invalid | The attribute type is invalid. |
| 400 | index_limit_exceeded | The maximum number of indexes has been reached. |
| 400 | index_invalid | Index invalid. |
| 400 | project_unknown | The project ID is either missing or not valid. Please check the value of the `X-Appwrite-Project` header to ensure the correct project ID is being used. |
| 400 | project_invalid_success_url | Invalid redirect URL for OAuth success. |
| 400 | project_invalid_failure_url | Invalid redirect URL for OAuth failure. |
| 400 | project_reserved_project | The project ID is reserved. Please choose another project ID. |
| 400 | project_smtp_config_invalid | Provided SMTP config is invalid. Please check the configured values and try again. |
| 400 | graphql_no_query | Param "query" is not optional. |
| 400 | graphql_too_many_queries | Too many queries. |
| 401 | general_access_forbidden | Access to this API is forbidden. |
| 401 | general_unauthorized_scope | The current user or API key does not have the required scopes to access the requested resource. |
| 401 | user_jwt_invalid | The JWT token is invalid. Please check the value of the `X-Appwrite-JWT` header to ensure the correct token is being used. |
| 401 | user_blocked | The current user has been blocked. You can unblock the user by making a request to the User API's "Update User Status" endpoint or in the Appwrite Console's Auth section. |
| 401 | user_invalid_token | Invalid token passed in the request. |
| 401 | user_email_not_whitelisted | Console registration is restricted to specific emails. Contact your administrator for more information. |
| 401 | user_invalid_code | The specified code is not valid. Contact your administrator for more information. |
| 401 | user_ip_not_whitelisted | Console registration is restricted to specific IPs. Contact your administrator for more information. |
| 401 | user_invalid_credentials | Invalid credentials. Please check the email and password. |
| 401 | user_anonymous_console_prohibited | Anonymous users cannot be created for the console project. |
| 401 | user_session_already_exists | Creation of anonymous users is prohibited when a session is active. |
| 401 | user_unauthorized | The current user is not authorized to perform the requested action. |
| 401 | user_oauth2_unauthorized | OAuth2 provider rejected the unauthorized request. |
| 401 | team_invalid_secret | The team invitation secret is invalid. Please request a new invitation and try again. |
| 401 | team_invite_mismatch | The invite does not belong to the current user. |
| 401 | project_key_expired | The project key has expired. Please generate a new key using the Appwrite console. |
| 401 | rule_verification_failed | Domain verification failed. Please check if your DNS records are correct and try again. |
| 401 | project_template_default_deletion | You can't delete default template. If you are trying to reset your template changes, you can ignore this error as it's already been reset. |
| 403 | general_unknown_origin | The request originated from an unknown origin. If you trust this domain, please list it as a trusted platform in the Appwrite console. |
| 403 | storage_invalid_file | The uploaded file is invalid. Please check the file and try again. |
| 403 | document_delete_restricted | Document cannot be deleted because it is referenced by another document. |
| 404 | general_route_not_found | The requested route was not found. Please refer to the API docs and try again. |
| 404 | user_not_found | User with the requested ID could not be found. |
| 404 | user_session_not_found | The current user session could not be found. |
| 404 | user_identity_not_found | The identity could not be found. Please sign in with OAuth provider to create identity first. |
| 404 | team_not_found | Team with the requested ID could not be found. |
| 404 | team_invite_not_found | The requested team invitation could not be found. |
| 404 | team_membership_mismatch | The membership ID does not belong to the team ID. |
| 404 | membership_not_found | Membership with the requested ID could not be found. |
| 404 | avatar_set_not_found | The requested avatar set could not be found. |
| 404 | avatar_not_found | The request avatar could not be found. |
| 404 | avatar_image_not_found | The requested image was not found at the URL. |
| 404 | avatar_remote_url_failed | Failed to fetch favicon from the requested URL. |
| 404 | avatar_icon_not_found | The requested favicon could not be found. |
| 404 | storage_file_not_found | The requested file could not be found. |
| 404 | storage_bucket_not_found | Storage bucket with the requested ID could not be found. |
| 404 | installation_not_found | Installation with the requested ID could not be found. Check to see if the ID is correct, or create the installation. |
| 404 | provider_repository_not_found | VCS (Version Control System) repository with the requested ID could not be found. Check to see if the ID is correct, and if it belongs to installationId you provided. |
| 404 | repository_not_found | Repository with the requested ID could not be found. Check to see if the ID is correct, or create the repository. |
| 404 | function_not_found | Function with the requested ID could not be found. |
| 404 | function_runtime_unsupported | The requested runtime is either inactive or unsupported. Please check the value of the `_APP_FUNCTIONS_RUNTIMES` environment variable. |
| 404 | function_runtime_unsupported | Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function's "Settings" > "Configuration" > "Entrypoint". |
| 404 | build_not_found | Build with the requested ID could not be found. |
| 404 | deployment_not_found | Deployment with the requested ID could not be found. |
| 404 | execution_not_found | Execution with the requested ID could not be found. |
| 404 | database_not_found | Database not found |
| 404 | collection_not_found | Collection with the requested ID could not be found. |
| 404 | document_not_found | Document with the requested ID could not be found. |
| 404 | attribute_not_found | Attribute with the requested ID could not be found. |
| 404 | index_not_found | Index with the requested ID could not be found. |
| 404 | project_not_found | Project with the requested ID could not be found. Please check the value of the `X-Appwrite-Project` header to ensure the correct project ID is being used. |
| 404 | router_host_not_found | Host is not trusted. This could occur because you have not configured a custom domain. Add a custom domain to your project first and try again. |
| 404 | rule_resource_not_found | Resource could not be found. Please check if the `resourceId` and `resourceType` are correct, or if the resource actually exists. |
| 404 | rule_not_found | Rule with the requested ID could not be found. Please check if the ID provided is correct or if the rule actually exists. |
| 404 | webhook_not_found | Webhook with the requested ID could not be found. |
| 404 | key_not_found | Key with the requested ID could not be found. |
| 404 | platform_not_found | Platform with the requested ID could not be found. |
| 404 | variable_not_found | Variable with the requested ID could not be found. |
| 404 | migration_not_found | Migration with the requested ID could not be found. Please verify that the provided ID is correct and try again. |
| 405 | general_not_implemented | This method was not fully implemented yet. If you believe this is a mistake, please upgrade your Appwrite server version. |
| 409 | user_already_exists | A user with the same id, email, or phone already exists in this project. |
| 409 | user_email_already_exists | A user with the same email already exists in the current project. |
| 409 | user_phone_already_exists | A user with the same phone number already exists in the current project. |
| 409 | team_invite_already_exists | User has already been invited or is already a member of this team |
| 409 | team_already_exists | Team with requested ID already exists. Please choose a different ID and try again. |
| 409 | membership_already_confirmed | Membership is already confirmed. |
| 409 | storage_file_already_exists | A storage file with the requested ID already exists. |
| 409 | storage_bucket_already_exists | A storage bucket with the requested ID already exists. Try again with a different ID or use `unique()` to generate a unique ID. |
| 409 | provider_contribution_conflict | External contribution is already authorized. |
| 409 | database_already_exists | Database already exists |
| 409 | collection_already_exists | A collection with the requested ID already exists. Try again with a different ID or use `unique()` to generate a unique ID. |
| 409 | document_already_exists | Document with the requested ID already exists. Try again with a different ID or use `unique()` to generate a unique ID. |
| 409 | document_update_conflict | Remote document is newer than local. |
| 409 | attribute_already_exists | Attribute with the requested ID already exists. Try again with a different ID or use `unique()` to generate a unique ID. |
| 409 | index_already_exists | Index with the requested ID already exists. Try again with a different ID or use `unique()` to generate a unique ID. |
| 409 | project_already_exists | Project with the requested ID already exists. Try again with a different ID or use `unique()` to generate a unique ID. |
| 409 | rule_already_exists | Domain is already used. Please try again with a different domain. |
| 409 | variable_already_exists | Variable with the same ID already exists in this project. Try again with a different ID. |
| 409 | migration_already_exists | Migration with the requested ID already exists. Try again with a different ID. |
| 409 | migration_in_progress | Migration is already in progress. You can check the status of the migration in your Appwrite Console's "Settings" > "Migrations". |
| 412 | user_password_reset_required | The current user requires a password reset. |
| 412 | project_provider_disabled | The chosen OAuth provider is disabled. You can enable the OAuth provider using the Appwrite console. |
| 416 | storage_invalid_range | The requested range is not satisfiable. Please check the value of the `Range` header. |
| 424 | user_oauth2_provider_error | OAuth2 provider returned some error. |
| 429 | general_rate_limit_exceeded | Rate limit for the current endpoint has been exceeded. Please try again after some time. |
| 500 | general_unknown | An unknown error has occurred. Please check the logs for more information. |
| 500 | general_server_error | An internal server error occurred. |
| 500 | general_protocol_unsupported | The request cannot be fulfilled with the current protocol. Please check the value of the `_APP_OPTIONS_FORCE_HTTPS` environment variable. |
| 500 | general_codes_disabled | Invitation codes are disabled on this server. Please contact the server administrator. |
| 500 | router_domain_not_configured | `_APP_DOMAIN`, `_APP_DOMAIN_TARGET`, and `_APP_DOMAIN_FUNCTIONS` environment variables have not been configured. Please configure the domain environment variables before accessing the Appwrite Console via any IP address or hostname other than localhost. This value could be an IP like 203.0.113.0 or a hostname like example.com. |
| 501 | general_usage_disabled | Usage stats is not configured. Please check the value of the `_APP_USAGE_STATS` environment variable of your Appwrite server. |
| 501 | user_count_exceeded | The current project has exceeded the maximum number of users. Please check your user limit in the Appwrite console. |
| 501 | user_auth_method_unsupported | The requested authentication method is either disabled or unsupported. Please check the supported authentication methods in the Appwrite console. |
| 501 | project_provider_unsupported | The chosen OAuth provider is unsupported. Please check the Create OAuth2 Session docs for the complete list of supported OAuth providers. |
| 503 | general_service_disabled | The requested service is disabled. You can enable the service from the Appwrite console. |
| 503 | general_smtp_disabled | SMTP is disabled on your Appwrite instance. You can learn more about setting up SMTP in our docs. |
| 503 | general_phone_disabled | Phone provider is not configured. Please check the `_APP_SMS_PROVIDER` environment variable of your Appwrite server. |

View File

@@ -11,38 +11,22 @@
{ {
label: 'Getting started', label: 'Getting started',
items: [ items: [
{
label: 'Overview',
href: '/docs/advanced/self-hosting'
},
{ {
label: 'Installation', label: 'Installation',
href: '/docs/advanced/self-hosting/installation' href: '/docs/advanced/self-hosting/'
} }
] ]
}, },
{ {
label: 'Guides', label: 'Guides',
items: [ items: [
{
label: 'Update',
href: '/docs/advanced/self-hosting/update'
},
{
label: 'Debugging',
href: '/docs/advanced/self-hosting/debug'
},
{
label: 'Email delivery',
href: '/docs/advanced/self-hosting/email'
},
{ {
label: 'Functions', label: 'Functions',
href: '/docs/advanced/self-hosting/functions' href: '/docs/advanced/self-hosting/functions'
}, },
{ {
label: 'Production', label: 'Email delivery',
href: '/docs/advanced/self-hosting/production' href: '/docs/advanced/self-hosting/email'
}, },
{ {
label: 'SMS delivery', label: 'SMS delivery',
@@ -52,10 +36,26 @@
label: 'Storage', label: 'Storage',
href: '/docs/advanced/self-hosting/storage' href: '/docs/advanced/self-hosting/storage'
}, },
{
label: 'Environment variables',
href: '/docs/advanced/self-hosting/environment-variables'
},
{ {
label: 'TLS Certificates', label: 'TLS Certificates',
href: '/docs/advanced/self-hosting/tls-certificates' href: '/docs/advanced/self-hosting/tls-certificates'
} },
{
label: 'Debugging',
href: '/docs/advanced/self-hosting/debug'
},
{
label: 'Production',
href: '/docs/advanced/self-hosting/production'
},
{
label: 'Update',
href: '/docs/advanced/self-hosting/update'
},
] ]
} }
]; ];

View File

@@ -1,25 +1,31 @@
--- ---
layout: article layout: article
title: Self-hosting title: Installation
description: Learn how to self host Appwrite on your own server using your favorite cloud provider. description: Learn how to integrate Appwrite in your application with one of the supported SDKs.
--- ---
Appwrite was designed from the ground up with self-hosting in mind. Appwrite was designed from the ground up with self-hosting in mind. You can install and run Appwrite on any operating system that can run a [Docker CLI](https://www.docker.com/products/docker-desktop). Self-hosted Appwrite instances can be configured flexibly with access to the same features found on Appwrite Cloud.
You can install and run Appwrite on any operating system that can run a [Docker CLI](https://www.docker.com/products/docker-desktop).
Self-hosted Appwrite instances can be configured flexibly with access to the same features found on Appwrite Cloud.
{% info title="Want to start building faster?" %} ## System requirements {% #system-requirements %}
Spend less time worrying about infrastructure and scaling, and spend more time building with [Appwrite Cloud](https://cloud.appwrite.io/).
{% /info %}
## System Requirements {% #system-requirements %}
Appwrite is designed to run well on both small and large deployments. The minimum requirements to run Appwrite are as little as **1 CPU core** and **2GB of RAM**, and an operating system that supports Docker. Appwrite is designed to run well on both small and large deployments. The minimum requirements to run Appwrite are as little as **1 CPU core** and **2GB of RAM**, and an operating system that supports Docker.
Appwrite requires [Docker Compose Version 2](https://docs.docker.com/compose/install/). To install Appwrite, make sure your Docker installation is updated to support Composer V2. Appwrite requires [Docker Compose Version 2](https://docs.docker.com/compose/install/). To install Appwrite, make sure your Docker installation is updated to support Composer V2.
## Get started {% #get-started %} {% info title="Upgrading From Older Versions" %}
Set up your first Appwrite instance with a single Docker command. If you are migrating from an older version of Appwrite, you need to follow the [migration instructions](/docs/advanced/self-hosting/update)
{% /info %}
## Install with Docker {% #install-with-docker %}
The easiest way to start running your Appwrite server is by running our Docker installer tool from your terminal. Before running the installation command, make sure you have [Docker CLI](https://www.docker.com/products/docker-desktop) installed on your host machine.
You will be prompted to configure the following during the setup command:
1. Your Appwrite instance's HTTP and HTTPS ports.
2. Your Appwrite instance's secret key used to encrypt sensitive data.
3. Your Appwrite instance's main hostname. Appwrite will generate a certificate using this hostname.
4. Your Appwrite instance's DNS A record hostname. Typically set to the same value as your Appwrite instance's hostname.
{% tabs %} {% tabs %}
{% tabsitem #unix title="macOS and Linux" %} {% tabsitem #unix title="macOS and Linux" %}
@@ -31,10 +37,6 @@ docker run -it --rm \
--entrypoint="install" \ --entrypoint="install" \
appwrite/appwrite:1.4.3 appwrite/appwrite:1.4.3
``` ```
After running the command, you can access the Appwrite Console and start building on `localhost`.
Read more about other ways to install and uninstall.
[Learn about install and uninstall {% icon icon="cheveron-right" /%}](#)
{% /tabsitem %} {% /tabsitem %}
{% tabsitem #windows title="Windows" %} {% tabsitem #windows title="Windows" %}
@@ -54,59 +56,58 @@ docker run -it --rm `
--entrypoint="install" ` --entrypoint="install" `
appwrite/appwrite:1.4.3 appwrite/appwrite:1.4.3
``` ```
After running the command, you can access the Appwrite Console and start building on `localhost`.
Read more about other ways to install and uninstall.
[Learn about install and uninstall {% icon icon="cheveron-right" /%}](#)
{% /tabsitem %} {% /tabsitem %}
{% /tabs %} {% /tabs %}
To unlock the full capabilities of Appwrite, read about the following configurations. ## One-click setups {% #one-click-setups %}
## Email delivery In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running with Appwrite quickly without installing Docker on your local machine.
Appwrite requires an SMTP service to deliver emails.
Email delivery is required for features like password recovery, account verification, MagicURL authentication, and team invites.
You can use a third-party SMTP service or host your own SMTP server.
[Configure email delivery {% icon icon="cheveron-right" /%}](#) Choose from one of the providers below:
&nbsp; |Provider | Installation Link
--- | --- | ---
{% icon icon="do" /%}| DigitalOcean | [Click to install](https://marketplace.digitalocean.com/apps/appwrite)
{% icon icon="gitpod" /%}| Gitpod | [Click to install](https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod)
{% icon icon="akamai" /%}| Akamai Compute | [Click to install](https://www.linode.com/marketplace/apps/appwrite/appwrite/)
## SMS delivery ## Next steps {% #next-steps %}
Appwrite supports multiple third-party SMS delivery providers.
SMS delivery is required for phone authentication.
[Configure SMS delivery {% icon icon="cheveron-right" /%}](#) Self-hosting Appwrite gives you more configurable options.
Make these configurations to unlock the full power of Appwrite.
## Functions [Configure Appwrite Functions](/docs/advanced/self-hosting/functions)
Appwrite supports 10+ function runtimes and automatic deployments through Git integration.
Before using Appwrite Functions, configure Git integration and enable runtimes.
[Configure Appwrite Functions {% icon icon="cheveron-right" /%}](#) [Configure email delivery](/docs/advanced/self-hosting/email)
## Storage [Configure SMS delivery](/docs/advanced/self-hosting/sms)
Appwrite's Storage Service can be configured to store files locally, or with self-hosted and cloud storage services.
By default, Appwrite's Storage Service stores files on your server's local storage.
If you expect large volumes of data or the need to have scalable data storage, you may choose to use a separate storage service.
[Configure Appwrite Storage {% icon icon="cheveron-right" /%}](#) [Configure Appwrite Storage](/docs/advanced/self-hosting/storage)
## TLS Certificates [Configure TLS Certificates](/docs/advanced/self-hosting/tls-certificates)
Appwrite uses Let's Encrypt to auto-generate TLS certificates for your Appwrite instance to ensure your API traffic is appropriately encrypted.
Configuration is required for Appwrite to properly generate certificates.
[Configure TLS certificates {% icon icon="cheveron-right" /%}](#) ## Manual (Docker Compose) {% #manual %}
## Debug For advanced Docker users, the manual installation might seem more familiar. To set up Appwrite manually, download the Appwrite base `docker-compose.yml` and `.env` files, then move them inside a directory named `appwrite`. After the download completes, update the different environment variables as you wish in the `.env` file and start the Appwrite stack using the following Docker command:
Appwrite provides tools to monitor server health, handle error logging.
[Learn about upgrade {% icon icon="cheveron-right" /%}](#) ```bash
docker compose up -d --remove-orphans
```
## Update Once the Docker installation completes, go to your machine's hostname or IP address on your browser to access the Appwrite Console. Please note that on hosts that are not Linux-native, the server might take a few minutes to start after installation completes.
Each Appwrite version contains a migration script to help you migrate your apps during updates.
[Learn about updates {% icon icon="cheveron-right" /%}](#) ## Stop {% #stop %}
## Production You can stop your Appwrite containers by using the following command executed from the same directory as your `docker-compose.yml` file.
Self-hosting Appwrite can be used in production settings.
To succeed with Appwrite in a production environment, you should follow a few basic concepts and best practices.
[Learn about production {% icon icon="cheveron-right" /%}](#) ```bash
docker compose stop
```
## Uninstall {% #uninstall %}
To stop and remove your Appwrite containers, you can use the following command executed from the same directory as your `docker-compose.yml` file.
```bash
docker compose down -v
```

View File

@@ -0,0 +1,203 @@
---
layout: article
title: Environment variables
description: Learn how to integrate Appwrite in your application with one of the supported SDKs.
---
Appwrite environment variables allow you to edit your server setup configuration and customize it. You can easily change the environment variables by changing them when running Appwrite using Docker CLI or Docker Compose.
Updating your Appwrite environment variables requires you to edit your Appwrite `.env` file. Your Docker files should be located inside the "appwrite" folder at the location where you first run the Appwrite installation script. It's recommended to use the `.env` file as a central point for updating your Appwrite configuration rather than changing them directly in your `docker-compose.yml` file.
After editing your `docker-compose.yml` or `.env` files, you will need to recreate your Appwrite stack by running the following compose command in your terminal:
```bash
docker compose up -d
```
You can verify if the changes have been successfully applied by running this command:
```bash
docker compose exec appwrite vars
```
## General {% #general %}
| Name | Description |
|------|-------------|
| `_APP_ENV` | Set your server running environment. By default, the var is set to 'development'. When deploying to production, change it to: 'production'. |
| `_APP_LOCALE` | Set your Appwrite's locale. By default, the locale is set to 'en'. |
| `_APP_OPTIONS_ABUSE` | Allows you to disable abuse checks and API rate limiting. By default, set to 'enabled'. To cancel the abuse checking, set to 'disabled'. It is not recommended to disable this check-in a production environment. |
| `_APP_OPTIONS_FORCE_HTTPS` | Allows you to force HTTPS connection to your API. This feature redirects any HTTP call to HTTPS and adds the 'Strict-Transport-Security' header to all HTTP responses. By default, set to 'enabled'. To disable, set to 'disabled'. This feature will work only when your ports are set to default 80 and 443. |
| `_APP_OPENSSL_KEY_V1` | This is your server private secret key that is used to encrypt all sensitive data on your server. Appwrite server encrypts all secret data on your server like webhooks, HTTP passwords, user sessions, and storage files. The var is not set by default, if you wish to take advantage of Appwrite encryption capabilities you should change it and make sure to **keep it a secret and have a backup for it**. |
| `_APP_DOMAIN` | Your Appwrite domain address. 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. The default value is 'localhost'. |
| `_APP_DOMAIN_FUNCTIONS` | A domain to use for function preview URLs. Setting to empty turns off function preview URLs. |
| `_APP_DOMAIN_TARGET` | A DNS A record 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. The default value is 'localhost'. |
| `_APP_CONSOLE_WHITELIST_ROOT`| This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by inviting them to your project. By default this option is enabled. |
| `_APP_CONSOLE_WHITELIST_EMAILS` | This option allows you to limit creation of new users on the Appwrite console. This option is very useful for small teams or sole developers. To enable it, pass a list of allowed email addresses separated by a comma. |
| `_APP_CONSOLE_WHITELIST_IPS` | This last option allows you to limit creation of users in Appwrite console for users sharing the same set of IP addresses. This option is very useful for team working with a VPN service or a company IP. To enable/activate this option, pass a list of allowed IP addresses separated by a comma. |
| `_APP_SYSTEM_EMAIL_NAME`| This is the sender name value that will appear on email messages sent to developers from the Appwrite console. The default value is: 'Appwrite'. You can use url encoded strings for spaces and special chars. |
| `_APP_SYSTEM_EMAIL_ADDRESS` | This is the sender email address that will appear on email messages sent to developers from the Appwrite console. The default value is 'team@appwrite.io'. You should choose an email address that is allowed to be used from your SMTP server to avoid the server email ending in the users' SPAM folders. |
| `_APP_SYSTEM_RESPONSE_FORMAT` | Use this environment variable to set the default Appwrite HTTP response format to support an older version of Appwrite. This option is useful to overcome breaking changes between versions. You can also use the `X-Appwrite-Response-Format` HTTP request header to overwrite the response for a specific request. This variable accepts any valid Appwrite version. To use the current version format, leave the value of the variable empty. |
| `_APP_SYSTEM_SECURITY_EMAIL_ADDRESS` | This is the email address used to issue SSL certificates for custom domains or the user agent in your webhooks payload. |
| `_APP_USAGE_STATS` | This variable allows you to disable the collection and displaying of usage stats. This value is set to 'enabled' by default, to disable the usage stats set the value to 'disabled'. When disabled, it's recommended to turn off the Worker Usage container to reduce resource usage. |
| `_APP_LOGGING_PROVIDER` | **(version >= 0.12.0)** This variable allows you to enable logging errors to 3rd party providers. This value is empty by default, set the value to one of 'sentry', 'raygun', 'appSignal', 'logOwl' to enable the logger. |
| `_APP_LOGGING_CONFIG` | **(version >= 0.12.0)** This variable configures authentication to 3rd party error logging providers. If using Sentry, this should be 'SENTRY_API_KEY;SENTRY_APP_ID'. If using Raygun, this should be Raygun API key. If using AppSignal, this should be AppSignal API key. If using LogOwl, this should be LogOwl Service Ticket. |
| `_APP_USAGE_AGGREGATION_INTERVAL` | **(version >= 1.1.0)** Interval value containing the number of seconds that the Appwrite usage process should wait before aggregating stats and syncing it to Database from TimeSeries data. The default value is 30 seconds. Reintroduced in 1.1.0. |
| `_APP_USAGE_TIMESERIES_INTERVAL` | **(version >= 1.0.0)** Deprecated since 1.1.0 use _APP_USAGE_AGGREGATION_INTERVAL instead. |
| `_APP_USAGE_DATABASE_INTERVAL` | **(version >= 1.0.0)** Deprecated since 1.1.0 use _APP_USAGE_AGGREGATION_INTERVAL instead. |
| `_APP_WORKER_PER_CORE` | **(version >= 0.13.0)** Internal Worker per core for the API, Realtime and Executor containers. Can be configured to optimize performance. |
## Redis {% #redis %}
Appwrite uses a Redis server for managing cache, queues and scheduled tasks. The Redis env vars are used to allow Appwrite server to connect to the Redis container.
| Name | Description |
|--------------------------|-------------------------------------------------------------------------------------------------------|
| `_APP_REDIS_HOST` | Redis server hostname address. Default value is: `redis`. |
| `_APP_REDIS_PORT` | Redis server TCP port. Default value is: `6379`. |
| `_APP_REDIS_USER` | Redis server user. This is an optional variable. Default value is an empty string. |
| `_APP_REDIS_PASS` | Redis server password. This is an optional variable. Default value is an empty string.|
Appwrite is using a MariaDB server for managing persistent database data. The MariaDB env vars are used to allow Appwrite server to connect to the MariaDB container.
| Name | Description |
|------------------------|--------------------------------------------------------------------------------------------------|
| `_APP_DB_HOST` | MariaDB server host name address. Default value is: `mariadb`. |
| `_APP_DB_PORT` | MariaDB server TCP port. Default value is: `3306`. |
| `_APP_DB_SCHEMA` | MariaDB server database schema. Default value is: `appwrite`. |
| `_APP_DB_USER` | MariaDB server user name. Default value is: `user`. |
| `_APP_DB_PASS` | MariaDB server user password. Default value is: `password`. |
| `_APP_DB_ROOT_PASS` | MariaDB server root password. Default value is: `rootsecretpassword`. |
## InfluxDB {% #influxdb %}
Appwrite uses an InfluxDB server for managing time-series data and server stats. The InfluxDB env vars are used to allow Appwrite server to connect to the InfluxDB container.
| Name | Description |
|-----------------------|-------------------------------------------------------------------------------------------------|
| `_APP_INFLUXDB_HOST` | InfluxDB server host name address. Default value is: `influxdb`. |
| `_APP_INFLUXDB_PORT` | InfluxDB server TCP port. Default value is: `8086`. |
## StatsD {% #statsd %}
Appwrite uses a StatsD server for aggregating and sending stats data over a fast UDP connection. The StatsD env vars are used to allow Appwrite server to connect to the StatsD container.
| Name | Description |
|---------------------|-------------------------------------------------------------------------------------|
| `_APP_STATSD_HOST` | StatsD server host name address. Default value is: `telegraf`. |
| `_APP_STATSD_PORT` | StatsD server TCP port. Default value is: `8125`. |
## SMTP {% #smtp %}
Appwrite is using an SMTP server for emailing your projects users and server admins. The SMTP env vars are used to allow Appwrite server to connect to the SMTP container.
If running in production, it might be easier to use a 3rd party SMTP server as it might be a little more difficult to set up a production SMTP server that will not send all your emails into your user's **spam folder**.
| Name | Description |
|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `_APP_SMTP_HOST` | SMTP server host name address. Use an empty string to disable all mail sending from the server. The default value for this variable is an empty string. |
| `_APP_SMTP_PORT` | SMTP server TCP port. Empty by default. |
| `_APP_SMTP_SECURE` | SMTP secure connection protocol. Empty by default, change to 'tls' if running on a secure connection. |
| `_APP_SMTP_USERNAME` | SMTP server user name. Empty by default. |
| `_APP_SMTP_PASSWORD` | SMTP server user password. Empty by default. |
## Phone {% #phone %}
| Name | Description |
|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `_APP_SMS_PROVIDER` | **version >= 0.15.0** Provider used for delivering SMS for Phone authentication. Use the following format: 'sms://[USER]:[SECRET]@[PROVIDER]'.<br>Ensure `[USER]` and `[SECRET]` are URL encoded if they contain any non-alphanumeric characters.<br>Available providers are twilio, text-magic, telesign, msg91, and vonage. |
| `_APP_SMS_FROM` | **version >= 0.15.0** Phone number used for sending out messages. Must start with a leading '+' and maximum of 15 digits without spaces (+123456789). |
## Storage {% #storage %}
| Name | Description |
|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `_APP_STORAGE_LIMIT` | **version >= 0.7.0** Maximum file size allowed for file upload. The default value is 30MB. You should pass your size limit value in bytes. |
| `_APP_STORAGE_PREVIEW_LIMIT` | **version >= 0.13.4** Maximum file size allowed for file image preview. The default value is 20MB. You should pass your size limit value in bytes. |
| `_APP_STORAGE_ANTIVIRUS` | This variable allows you to disable the internal anti-virus scans. This value is set to 'disabled' by default, to enable the scans set the value to 'enabled'. Before enabling, you must add the ClamAV service and depend on it on main Appwrite service. |
| `_APP_STORAGE_ANTIVIRUS_HOST` | **version >= 0.7.0** ClamAV server host name address. Default value is: 'clamav'. |
| `_APP_STORAGE_ANTIVIRUS_PORT` | **version >= 0.7.0** ClamAV server TCP port. Default value is: '3310'. |
| `_APP_STORAGE_DEVICE` | **version >= 0.13.0** Select default storage device. The default value is 'local'. List of supported adapters are 'local', 's3', 'dospaces', 'backblaze', 'linode' and 'wasabi'. |
| `_APP_STORAGE_S3_ACCESS_KEY` | **version >= 0.13.0** AWS S3 storage access key. Required when the storage adapter is set to S3. You can get your access key from your AWS console. |
| `_APP_STORAGE_S3_SECRET` | **version >= 0.13.0** AWS S3 storage secret key. Required when the storage adapter is set to S3. You can get your secret key from your AWS console. |
| `_APP_STORAGE_S3_REGION` | **version >= 0.13.0** AWS S3 storage region. Required when storage adapter is set to S3. You can find your region info for your bucket from AWS console. |
| `_APP_STORAGE_S3_BUCKET` | **version >= 0.13.0** AWS S3 storage bucket. Required when storage adapter is set to S3. You can create buckets in your AWS console. |
| `_APP_STORAGE_DO_SPACES_ACCESS_KEY` | **version >= 0.13.0** DigitalOcean spaces access key. Required when the storage adapter is set to DOSpaces. You can get your access key from your DigitalOcean console. |
| `_APP_STORAGE_DO_SPACES_SECRET` | **version >= 0.13.0** DigitalOcean spaces secret key. Required when the storage adapter is set to DOSpaces. You can get your secret key from your DigitalOcean console. |
| `_APP_STORAGE_DO_SPACES_REGION` | **version >= 0.13.0** DigitalOcean spaces region. Required when storage adapter is set to DOSpaces. You can find your region info for your space from DigitalOcean console. |
| `_APP_STORAGE_DO_SPACES_BUCKET` | **version >= 0.13.0** DigitalOcean spaces bucket. Required when storage adapter is set to DOSpaces. You can create spaces in your DigitalOcean console. |
| `_APP_STORAGE_BACKBLAZE_ACCESS_KEY` | **version >= 0.14.2** Backblaze access key. Required when the storage adapter is set to Backblaze. Your Backblaze keyID will be your access key. You can get your keyID from your Backblaze console. |
| `_APP_STORAGE_BACKBLAZE_SECRET` | **version >= 0.14.2** Backblaze secret key. Required when the storage adapter is set to Backblaze. Your Backblaze applicationKey will be your secret key. You can get your applicationKey from your Backblaze console. |
| `_APP_STORAGE_BACKBLAZE_REGION` | **version >= 0.14.2** Backblaze region. Required when storage adapter is set to Backblaze. You can find your region info from your Backblaze console. |
| `_APP_STORAGE_BACKBLAZE_BUCKET` | **version >= 0.14.2** Backblaze bucket. Required when storage adapter is set to Backblaze. You can create your bucket from your Backblaze console. |
| `_APP_STORAGE_LINODE_ACCESS_KEY` | **version >= 0.14.2** Linode object storage access key. Required when the storage adapter is set to Linode. You can get your access key from your Linode console. |
| `_APP_STORAGE_LINODE_SECRET` | **version >= 0.14.2** Linode object storage secret key. Required when the storage adapter is set to Linode
## Functions {% #functions %}
| **Name** | **Description** |
|-------------------------------|-----------------|
| `_APP_FUNCTIONS_SIZE_LIMIT` | **version >= 0.13.0** The maximum size deployment in bytes. The default value is 30MB. |
| `_APP_FUNCTIONS_TIMEOUT` | **version >= 0.7.0** The maximum number of seconds allowed as a timeout value when creating a new function. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the function's settings or in appwrite.json. |
| `_APP_FUNCTIONS_BUILD_TIMEOUT`| **version >= 0.13.0** The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds. |
| `_APP_FUNCTIONS_CONTAINERS` | **version >= 0.7.0** Deprecated since 1.2.0. Runtimes now timeout by inactivity using `_APP_FUNCTIONS_INACTIVE_THRESHOLD`. |
| `_APP_FUNCTIONS_CPUS` | **version >= 0.7.0** The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it's empty, CPU limit will be disabled. |
| `_APP_FUNCTIONS_MEMORY` | **version >= 0.7.0** The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it's empty, memory limit will be disabled. |
| `_APP_FUNCTIONS_MEMORY_SWAP` | **version >= 0.7.0** Deprecated since 1.2.0. High use of swap memory is not recommended to preserve harddrive health. |
| `_APP_FUNCTIONS_RUNTIMES` | **version >= 0.8.0** This option allows you to enable or disable runtime environments for cloud functions. Disable unused runtimes to save disk space. To enable cloud function runtimes, pass a list of enabled environments separated by a comma. [Learn more about runtimes](/docs/products/functions/runtimes).|
| `_APP_EXECUTOR_SECRET` | **version >= 0.13.0** The secret key used by Appwrite to communicate with the function executor. Make sure to change this! |
| `_APP_EXECUTOR_HOST` | **version >= 0.13.0** The host used by Appwrite to communicate with the function executor! |
| `_APP_EXECUTOR_RUNTIME_NETWORK`| **version >= 0.13.0** Deprecated with 0.14.0, use `OPEN_RUNTIMES_NETWORK` instead! |
| `_APP_FUNCTIONS_ENVS` | **version >= 0.7.0** Deprecated with 0.8.0, use `_APP_FUNCTIONS_RUNTIMES` instead! |
| `_APP_FUNCTIONS_INACTIVE_THRESHOLD`| **version >= 0.13.0** The minimum time a function must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds. |
| `DOCKERHUB_PULL_USERNAME` | **version >= 0.10.0** Deprecated with 1.2.0, use `_APP_DOCKER_HUB_USERNAME` instead! |
| `DOCKERHUB_PULL_PASSWORD` | **version >= 0.10.0** Deprecated with 1.2.0, use `_APP_DOCKER_HUB_PASSWORD` instead! |
| `DOCKERHUB_PULL_EMAIL` | **version >= 0.10.0** Deprecated since 1.2.0. Email is no longer needed. |
| `OPEN_RUNTIMES_NETWORK` | **version >= 0.13.0** Deprecated with 1.2.0, use `_APP_FUNCTIONS_RUNTIMES_NETWORK` instead! |
| `_APP_FUNCTIONS_RUNTIMES_NETWORK`| **version >= 1.2.0** The docker network used for communication between the executor and runtimes. |
| `_APP_DOCKER_HUB_USERNAME` | **version >= 1.2.0** The username for hub.docker.com. This variable is used to pull images from hub.docker.com. |
| `_APP_DOCKER_HUB_PASSWORD` | **version >= 1.2.0** The password for hub.docker.com. This variable is used to pull images from hub.docker.com. |
| `_APP_FUNCTIONS_MAINTENANCE_INTERVAL`| **version >= 1.4.0** Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour). |
## VCS (Version Control System) {% #vcs %}
| **Name** | **Description** |
|---------------------------------|-----------------------------------------------------------------------------------------------------------------|
| `_APP_VCS_GITHUB_APP_NAME` | **version >= 1.4.0** - Name of your GitHub app. This value should be set to your GitHub application's URL. |
| `_APP_VCS_GITHUB_PRIVATE_KEY` | **version >= 1.4.0** - GitHub app RSA private key. You can generate private keys from GitHub application settings. |
| `_APP_VCS_GITHUB_APP_ID` | **version >= 1.4.0** - GitHub application ID. You can find it in your GitHub application details. |
| `_APP_VCS_GITHUB_CLIENT_ID` | **version >= 1.4.0** - GitHub client ID. You can find it in your GitHub application details. |
| `_APP_VCS_GITHUB_CLIENT_SECRET` | **version >= 1.4.0** - GitHub client secret. You can generate secrets in your GitHub application settings. |
| `_APP_VCS_GITHUB_WEBHOOK_SECRET`| **version >= 1.4.0** - GitHub webhook secret. You can configure it in your GitHub application settings under webhook section. |
## Maintenance {% #maintenance %}
| **Name** | **Description** |
|-------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `_APP_MAINTENANCE_INTERVAL` | **version >= 0.7.0** - Interval value containing the number of seconds that the Appwrite maintenance process should wait before executing system cleanups and optimizations. The default value is `86400` seconds (1 day). |
| `_APP_MAINTENANCE_RETENTION_CACHE` | **version >= 1.0.0** - The maximum duration (in seconds) upto which to retain cached files. The default value is `2592000` seconds (30 days). |
| `_APP_MAINTENANCE_RETENTION_EXECUTION` | **version >= 0.7.0** - The maximum duration (in seconds) upto which to retain execution logs. The default value is `1209600` seconds (14 days). |
| `_APP_MAINTENANCE_RETENTION_AUDIT` | **version >= 0.7.0** - The maximum duration (in seconds) upto which to retain audit logs. The default value is `1209600` seconds (14 days). |
| `_APP_MAINTENANCE_RETENTION_ABUSE` | **version >= 0.7.0** - The maximum duration (in seconds) upto which to retain abuse logs. The default value is `86400` seconds (1 day). |
| `_APP_MAINTENANCE_RETENTION_USAGE_HOURLY` | The maximum duration (in seconds) upto which to retain hourly usage metrics. The default value is `8640000` seconds (100 days). |
| `_APP_MAINTENANCE_RETENTION_SCHEDULES` | Schedules deletion interval (in seconds). |
## GraphQL {% #graphql %}
| **Name** | **Description** |
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `_APP_GRAPHQL_MAX_BATCH_SIZE` | **version >= 1.2.0** - Maximum number of batched queries per request. The default value is 10. |
| `_APP_GRAPHQL_MAX_COMPLEXITY` | **version >= 1.2.0** - Maximum complexity of a GraphQL query. One field adds one to query complexity. Lists multiply the complexity by the number of items requested. The default value is 250. |
| `_APP_GRAPHQL_MAX_DEPTH` | **version >= 1.2.0** - Maximum depth of a GraphQL query. One nested field level adds one to query depth. The default value is 3. |
## Migrations {% #migrations %}
| **Name** | **Description** |
|-------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| `_APP_MIGRATIONS_FIREBASE_CLIENT_ID` | **version >= 1.4.0** - Google OAuth client ID. You can find it in your GCP application settings. |
| `_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET` | **version >= 1.4.0** - Google OAuth client secret. You can generate secrets in your GCP application settings. |
## Assistant {% #assistant %}
| **Name** | **Description** |
|----------------------------------------|-------------------------------------------------------------------------|
| `_APP_ASSISTANT_OPENAI_API_KEY` | **version >= 1.4.0** - OpenAI API key. You can find it in your OpenAI application settings. |

View File

@@ -105,7 +105,7 @@ _APP_VCS_GITHUB_CLIENT_SECRET=35rsdse532q13
_APP_VCS_GITHUB_WEBHOOK_SECRET=super-secret _APP_VCS_GITHUB_WEBHOOK_SECRET=super-secret
``` ```
[Learn more about environment variables](#) [Learn more about environment variables](/docs/advanced/self-hosting/environment-variables)
### Update exiting GitHub apps {% #existing-apps %} ### Update exiting GitHub apps {% #existing-apps %}
@@ -125,7 +125,7 @@ The example below would enable Dart 2.15, .NET 6.0, and Java 18 runtimes.
_APP_FUNCTIONS_RUNTIMES=dart-2.15, dotnet-6.0, java-18.0 _APP_FUNCTIONS_RUNTIMES=dart-2.15, dotnet-6.0, java-18.0
``` ```
You can find a full list of supported runtimes on the [environment variables page](#). You can find a full list of supported runtimes on the [environment variables page](/docs/advanced/self-hosting/environment-variables).
You can also configure the maximum timeout that can be set on individual Appwrite functions. The maximum configurable timeout can be increased by changing the `_APP_FUNCTIONS_TIMEOUT` environment variable. This environment variable changes the configurable maximum but does not alter existing configurations of individual functions. You can also configure the maximum timeout that can be set on individual Appwrite functions. The maximum configurable timeout can be increased by changing the `_APP_FUNCTIONS_TIMEOUT` environment variable. This environment variable changes the configurable maximum but does not alter existing configurations of individual functions.

View File

@@ -65,22 +65,42 @@ In addition to running Appwrite locally, you can also launch Appwrite using a pr
Choose from one of the providers below: Choose from one of the providers below:
&nbsp; |Provider | Installation Link {% table %}
--- | --- | --- * &nbsp;
{% icon icon="digitalocean" /%}| DigitalOcean | [Click to install](https://marketplace.digitalocean.com/apps/appwrite) * Provider
{% icon icon="gitpod" /%}| Gitpod | [Click to install](https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod) * Installation Link
{% icon icon="akamai" /%}| Akamai Compute | [Click to install](https://www.linode.com/marketplace/apps/appwrite/appwrite/) ---
* {% only_dark %}{% icon_image src="/images/one-click/dark/digitalocean.svg" alt="DigitalOcean logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/one-click/digitalocean.svg" alt="DigitalOcean logo" size="m" /%}{% /only_light %}
* DigitalOcean
* [Click to install](https://marketplace.digitalocean.com/apps/appwrite)
---
* {% only_dark %}{% icon_image src="/images/one-click/dark/gitpod.svg" alt="Gitpod logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/one-click/gitpod.svg" alt="Gitpod logo" size="m" /%}{% /only_light %}
* Gitpod
* [Click to install](https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod)
---
* {% only_dark %}{% icon_image src="/images/one-click/dark/akamai.svg" alt="Akamai logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/one-click/akamai.svg" alt="Akamai logo" size="m" /%}{% /only_light %}
* Akamai Compute
* [Click to install](https://www.linode.com/marketplace/apps/appwrite/appwrite/)
{% /table %}
## Next steps {% #next-steps %} ## Next steps {% #next-steps %}
Self-hosting Appwrite gives you more configurable options. Self-hosting Appwrite gives you more configurable options.
Make these configurations to unlock the full power of Appwrite. Make these configurations to unlock the full power of Appwrite.
- [Configure email delivery](#) [Configure Appwrite Functions](/docs/advanced/self-hosting/functions)
- [Configure SMS delivery](#)
- [Configure Appwrite Functions](#) [Configure email delivery](/docs/advanced/self-hosting/email)
- [Configure Appwrite Storage](#)
- [Configure TLS Certificates](#) [Configure SMS delivery](/docs/advanced/self-hosting/sms)
[Configure Appwrite Storage](/docs/advanced/self-hosting/storage)
[Configure TLS Certificates](/docs/advanced/self-hosting/tls-certificates)
## Manual (Docker Compose) {% #manual %} ## Manual (Docker Compose) {% #manual %}

View File

@@ -16,7 +16,7 @@ Make sure to keep this key in a safe place and never make it publicly accessible
{% info title="Best practice" %} {% info title="Best practice" %}
You should always prefer **HTTPS** over HTTP in production environments. This keeps your APIs secure and prevents any redirects from interfering with your requests. You should always prefer **HTTPS** over HTTP in production environments. This keeps your APIs secure and prevents any redirects from interfering with your requests.
You can force the use of HTTPS with the [_APP_OPTIONS_FORCE_HTTPS](#) environment variable. You can force the use of HTTPS with the [_APP_OPTIONS_FORCE_HTTPS](/docs/advanced/self-hosting/environment-variables) environment variable.
{% /info %} {% /info %}
## Console access {% #console-access %} ## Console access {% #console-access %}
@@ -29,7 +29,7 @@ Appwrite provides three different methods to limit access to your Appwrite Conso
By default, only the first user can sign up on the Appwrite instance's dashboard. All other users must be added to the dashboard through invitation. By default, only the first user can sign up on the Appwrite instance's dashboard. All other users must be added to the dashboard through invitation.
[Learn more about environment variables {% icon icon="cheveron-right" /%}](#) [Learn more about environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Scaling {% #scaling %} ## Scaling {% #scaling %}
@@ -47,7 +47,7 @@ If you disabled rate limits during development, make sure you re-enable them whe
Rate limits are an important mechanism to protect your app. Without rate limits, malicious actors can spam your APIs to perform [denial-of-service type attacks](https://en.wikipedia.org/wiki/Denial-of-service_attack) or brute-force user passwords. Rate limits are an important mechanism to protect your app. Without rate limits, malicious actors can spam your APIs to perform [denial-of-service type attacks](https://en.wikipedia.org/wiki/Denial-of-service_attack) or brute-force user passwords.
[Learn more about environment variables {% icon icon="cheveron-right" /%}](#) [Learn more about environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Emails {% #emails %} ## Emails {% #emails %}
@@ -70,7 +70,7 @@ Do not back up any stateful container using a docker volume backup, such as data
## Errors {% #errors %} ## Errors {% #errors %}
By default, your Appwrite installation comes with error reporting turned off. You can [enable dev mode](#) to get access to more verbose error logs and stack traces. By default, your Appwrite installation comes with error reporting turned off. You can [enable dev mode](/docs/advanced/self-hosting/debug#development-mode) to get access to more verbose error logs and stack traces.
In production, it is highly recommended to turn error reporting off. To do so, make sure the Appwrite container environment variable `_APP_ENV` value from is set to `production` and not `development`. In production, it is highly recommended to turn error reporting off. To do so, make sure the Appwrite container environment variable `_APP_ENV` value from is set to `production` and not `development`.
@@ -78,7 +78,7 @@ To monitor errors in production, add a third party monitoring service by setting
In production, it is highly recommended to turn error reporting off. To do so, make sure the Appwrite container environment variable `_APP_ENV` is set to `production` and not `development`. In production, it is highly recommended to turn error reporting off. To do so, make sure the Appwrite container environment variable `_APP_ENV` is set to `production` and not `development`.
[Learn more about environment variables {% icon icon="cheveron-right" /%}](#) [Learn more about environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Security {% #security %} ## Security {% #security %}

View File

@@ -6,18 +6,46 @@ description: Learn how to integrate Appwrite in your application with one of the
Appwrite supports phone authentication, which allows users to create accounts and log in using SMS messages. Appwrite requires an SMS provider to be set up before using Phone authentication. Appwrite supports phone authentication, which allows users to create accounts and log in using SMS messages. Appwrite requires an SMS provider to be set up before using Phone authentication.
## SMS Providers {% #sms-providers %} ## SMS providers {% #sms-providers %}
Appwrite supports a growing list of SMS providers that you can choose from. Choose one from the list below and set up an account. Appwrite supports a growing list of SMS providers that you can choose from. Choose one from the list below and set up an account.
| &nbsp; | SMS Provider | Create Account | Get Credentials | {% table %}
| ----------------- | -------------- | ------------------------------------------------------- | ----------------------------------------------------- | * &nbsp; {% width=80 %}
| | | | | * SMS provider
| [TODO] | Twilio | [Website](https://www.twilio.com) | [Documentation](https://www.twilio.com/docs/iam/access-tokens#step-2-api-key) | * Create account
| [TODO] | TextMagic | [Website](https://www.textmagic.com) | [Documentation](https://www.textmagic.com/docs/api/start/#How-to-obtain-the-API-credentials) | * Get credentials
| [TODO] | Telesign | [Website](https://www.telesign.com) | [Documentation](https://support.telesign.com/s/article/Find-Customer-ID-and-API-Key) | ---
| [TODO] | MSG91 | [Website](https://msg91.com) | [Documentation](https://msg91.com/help/where-can-i-find-my-authentication-key) | * {% only_dark %}{% icon_image src="/images/sms-providers/dark/twilio.svg" alt="Twilio logo" size="l" /%}{% /only_dark %}
| [TODO] | Vonage | [Website](https://www.vonage.ca/) | [Documentation](https://developer.vonage.com/en/account/secret-management) | {% only_light %}{% icon_image src="/images/sms-providers/twilio.svg" alt="Twilio logo" size="l" /%}{% /only_light %}
* Twilio
* [Website](https://www.twilio.com)
* [Documentation](https://www.twilio.com/docs/iam/access-tokens#step-2-api-key)
---
* {% only_dark %}{% icon_image src="/images/sms-providers/dark/textmagic.svg" alt="TextMagic logo" size="l" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/sms-providers/textmagic.svg" alt="TextMagic logo" size="l" /%}{% /only_light %}
* TextMagic
* [Website](https://www.textmagic.com)
* [Documentation](https://www.textmagic.com/docs/api/start/#How-to-obtain-the-API-credentials)
---
* {% only_dark %}{% icon_image src="/images/sms-providers/dark/telesign.svg" alt="Telesign logo" size="l" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/sms-providers/telesign.svg" alt="Telesign logo" size="l" /%}{% /only_light %}
* Telesign
* [Website](https://www.telesign.com)
* [Documentation](https://support.telesign.com/s/article/Find-Customer-ID-and-API-Key)
---
* {% only_dark %}{% icon_image src="/images/sms-providers/dark/msg91.svg" alt="MSG91 logo" size="l" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/sms-providers/msg91.svg" alt="MSG91 logo" size="l" /%}{% /only_light %}
* MSG91
* [Website](https://msg91.com)
* [Documentation](https://msg91.com/help/where-can-i-find-my-authentication-key)
---
* {% only_dark %}{% icon_image src="/images/sms-providers/dark/vonage.svg" alt="Vonage logo" size="l" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/sms-providers/vonage.svg" alt="Vonage logo" size="l" /%}{% /only_light %}
* Vonage
* [Website](https://www.vonage.ca/)
* [Documentation](https://developer.vonage.com/en/account/secret-management)
{% /table %}
## Environment variables {% #environment-variables %} ## Environment variables {% #environment-variables %}

View File

@@ -14,11 +14,11 @@ Some of these services can be self-hosted, just like Appwrite.
You can select which storage adapter to use by setting the `_APP_STORAGE_DEVICE` environment variable. Valid values are `local`, `s3`, `dospaces`, `backblaze`, `linode`, and `wasabi`. Each storage adapter requires its own set of additional environment variables to configure. You can select which storage adapter to use by setting the `_APP_STORAGE_DEVICE` environment variable. Valid values are `local`, `s3`, `dospaces`, `backblaze`, `linode`, and `wasabi`. Each storage adapter requires its own set of additional environment variables to configure.
[Learn more about storage environment variables {% icon icon="cheveron-right" /%}](#) [Learn more about storage environment variables {% icon icon="cheveron-right" /%}](/docs/advanced/self-hosting/environment-variables)
## Maximum file size {% #adapters %} ## Maximum file size {% #adapters %}
The maximum size for a single file upload is controlled by the `_APP_STORAGE_LIMIT` environment variable, which defaults to 30 MB. The maximum size for a single file upload is controlled by the `_APP_STORAGE_LIMIT` environment variable, which defaults to 30 MB.
See [Environment Variables](#) for more information. [Learn more about environment variables](/docs/advanced/self-hosting/environment-variables).
{% partial file="update-variables.md" /%} {% partial file="update-variables.md" /%}

View File

@@ -26,7 +26,7 @@ parent_directory <= you run the command in this directory
This is the parent directory where you will find the `appwrite directory, inside which there are `docker-compose.yml` and `.env` files. This is the parent directory where you will find the `appwrite directory, inside which there are `docker-compose.yml` and `.env` files.
## [Installing the Next Version](#) ## Installing the next version {% #install-next-version %}
### Unix ### Unix

View File

@@ -93,7 +93,7 @@ To subscribe to updates from different Appwrite resources, you need to specify o
If you subscribe to a channel, you will receive callbacks for a variety of events related to the channel. The events attribute in the callback can be used to filter and respond to specific events in a channel. If you subscribe to a channel, you will receive callbacks for a variety of events related to the channel. The events attribute in the callback can be used to filter and respond to specific events in a channel.
[View a list of all available events](#). [View a list of all available events](/docs/advanced/platform/events).
{% info title="Permissions" %} {% info title="Permissions" %}
@@ -337,7 +337,7 @@ The payload from the subscription will contain following properties:
--- ---
* events * events
* string[] * string[]
* The [system events](#) that triggered this update. * The [Appwrite events](/docs/advanced/platform/events) that triggered this update.
--- ---
* channels * channels
* string[] * string[]

View File

@@ -31,7 +31,7 @@ Appwrite's REST APIs expect certain headers to be included with each request:
--- ---
* X-Appwrite-JWT: [TOKEN] * X-Appwrite-JWT: [TOKEN]
* optional * optional
* Token used for JWT authentication, tokens can be generated using the [Create JWT](/docs/products/auth/server-integrations) method. * Token used for JWT authentication, tokens can be generated using the [Create JWT](/docs/products/auth/jwt) method.
--- ---
* X-Appwrite-Response-Format: [VERSION-NUMBER] * X-Appwrite-Response-Format: [VERSION-NUMBER]
* optional * optional
@@ -95,7 +95,7 @@ X-Appwrite-Key: [API_KEY]
### JWT ### JWT
JWT authentication is frequently used by server applications to act on behalf of a user. Users generate tokens using the [Create JWT] (TODO) endpoint. When issuing requests authenticated with a JWT, Appwrite will treat the request like it is from the authenticated user. JWT authentication is frequently used by server applications to act on behalf of a user. Users generate tokens using the [Create JWT](/docs/references/cloud/client-web/account#createJWT) endpoint. When issuing requests authenticated with a JWT, Appwrite will treat the request like it is from the authenticated user.
```json ```json
GET /v1/account HTTP/1.1 GET /v1/account HTTP/1.1
@@ -108,7 +108,7 @@ X-Appwrite-JWT: [TOKEN]
Appwrite implements resumable, chunked uploads for files larger than 5MB. Chunked uploads send files in chunks of 5MB to reduce memory footprint and increase resilience when handling large files. Appwrite SDKs will automatically handle chunked uploads, but it is possible to implement this with the REST API directly. Appwrite implements resumable, chunked uploads for files larger than 5MB. Chunked uploads send files in chunks of 5MB to reduce memory footprint and increase resilience when handling large files. Appwrite SDKs will automatically handle chunked uploads, but it is possible to implement this with the REST API directly.
Upload endpoints in Appwrite, such as [Create File] (todo) and [Create Deployment] (todo), are different from other endpoints. These endpoints take multipart form data instead of JSON data. To implement chunked uploads, you will need to implement the following headers. If you wish, this logic is already available in any of the [Appwrite SDKs](/docs/sdks). Upload endpoints in Appwrite, such as [Create File] (/docs/references/cloud/client-web/storage#createFile) and [Create Deployment] (/docs/references/cloud/server-nodejs/functions#createDeployment), are different from other endpoints. These endpoints take multipart form data instead of JSON data. To implement chunked uploads, you will need to implement the following headers. If you wish, this logic is already available in any of the [Appwrite SDKs](/docs/sdks).
{% table %} {% table %}
* Header * Header

View File

@@ -21,6 +21,31 @@
} }
] ]
}, },
{
label: 'Concepts',
items: [
{
label: 'Accounts',
href: '/docs/products/auth/accounts'
},
{
label: 'Users',
href: '/docs/products/auth/users'
},
{
label: 'Teams',
href: '/docs/products/auth/teams'
},
{
label: 'Labels',
href: '/docs/products/auth/labels'
},
{
label: 'Security',
href: '/docs/products/auth/security'
}
]
},
{ {
label: 'Journeys', label: 'Journeys',
items: [ items: [
@@ -46,31 +71,10 @@
}, },
{ {
label: 'JWT login', label: 'JWT login',
href: '/docs/products/auth/server-integrations' href: '/docs/products/auth/jwt'
}, },
] ]
}, },
{
label: 'Concepts',
items: [
{
label: 'Accounts',
href: '/docs/products/auth/accounts'
},
{
label: 'Teams',
href: '/docs/products/auth/teams'
},
{
label: 'Labels',
href: '/docs/products/auth/labels'
},
{
label: 'Security',
href: '/docs/products/auth/security'
}
]
},
{ {
label: 'References', label: 'References',
items: [ items: [
@@ -83,7 +87,7 @@
href: '/docs/references/cloud/server-nodejs/users' href: '/docs/references/cloud/server-nodejs/users'
}, },
{ {
label: 'Users API', label: 'Teams API',
href: '/docs/references/cloud/client-web/teams' href: '/docs/references/cloud/client-web/teams'
} }
] ]

View File

@@ -1,6 +1,6 @@
--- ---
layout: article layout: article
title: Authentication title: Overview
description: This is the description used for SEO. description: This is the description used for SEO.
back: /docs back: /docs
--- ---

View File

@@ -4,7 +4,7 @@ title: Accounts
description: This is the description used for SEO. description: This is the description used for SEO.
--- ---
Appwrite allows users to create accounts. Appwrite Account API is used for user signup and login in client applications.
Users can be organized into teams and be given labels, so they can be given different permissions and access different resources. Users can be organized into teams and be given labels, so they can be given different permissions and access different resources.
Each user's account can also have their own preference object, which you can use to save preferences such as theme, language, and notification settings. Each user's account can also have their own preference object, which you can use to save preferences such as theme, language, and notification settings.
@@ -22,7 +22,7 @@ authentication.
## Preferences {% #preferences %} ## Preferences {% #preferences %}
You can store user preferences on a user's account using Appwrite's [Update Preferences](#) endpoint. You can store preferences such as theme, notification settings, or preferred language so they can be synced across multiple devices. You can store user preferences on a user's account using Appwrite's [Update Preferences](/docs/references/cloud/client-web/account#updatePrefs) endpoint. You can store preferences such as theme, notification settings, or preferred language so they can be synced across multiple devices.
Preferences are stored as a key-value JSON object. The maximum allowed size for preferences is 64kB, and an error will be thrown if this limit is exceeded. Preferences are stored as a key-value JSON object. The maximum allowed size for preferences is 64kB, and an error will be thrown if this limit is exceeded.
@@ -108,7 +108,7 @@ mutation {
``` ```
{% /multicode %} {% /multicode %}
After a user's preferences are updated, they can be retrieved using the [Get Preferences](#) endpoint. After a user's preferences are updated, they can be retrieved using the [get account preferences](/docs/references/cloud/client-web/account#getPrefs) endpoint.
{% multicode %} {% multicode %}
```js ```js
@@ -183,4 +183,6 @@ individual users using the `Role.user(<USER_ID>, <STATUS>)` role.
| Verified user | `Role.user(<USER_ID>, 'verified')`| | Verified user | `Role.user(<USER_ID>, 'verified')`|
| Unverified user | `Role.user(<USER_ID>, 'unverified')` | | Unverified user | `Role.user(<USER_ID>, 'unverified')` |
[Learn more about permissions](/docs/advanced/platform/permissions)
[Learn more about permissions {% icon icon="cheveron-right" /%}](/docs/advanced/platform/permissions)

View File

@@ -4,13 +4,13 @@ title: Anonymous login
description: This is the description used for SEO. description: This is the description used for SEO.
--- ---
Anonymous sessions allow you to implement guest users. Guest users let you store user information like items in their cart or theme preferences before they create an account. This reduces the friction for your users to get started with your app. Anonymous sessions allow you to implement **guest** users. Guest users let you store user information like items in their cart or theme preferences before they create an account. This reduces the friction for your users to get started with your app.
**If a user later creates an account**, their information will be inherited by the newly created account. **If a user later creates an account**, their information will be inherited by the newly created account.
## Create anonymous session {% #createSession %} ## Create anonymous session {% #createSession %}
Create an anonymous session with [Create Anonymous Session](#) route. Create an anonymous session with [Create Anonymous Session](/docs/references/cloud/client-web/account#createAnonymousSession) route.
{% multicode %} {% multicode %}
```js ```js
@@ -82,7 +82,10 @@ Anonymous users cannot sign back in. If the session expires, they move to anothe
Create an account with any of these methods to transition from an anonymous session to a user account session. Create an account with any of these methods to transition from an anonymous session to a user account session.
- [Email and password](/docs/products/auth/email-password) [Email and password {% icon icon="cheveron-right" /%}](/docs/products/auth/email-password)
- [Phone (SMS)](/docs/products/auth/phone-sms)
- [Magic URL](/docs/products/auth/magic-url) [Phone (SMS) {% icon icon="cheveron-right" /%}](/docs/products/auth/phone-sms)
- [OAuth2](/docs/products/auth/oauth2)
[Magic URL {% icon icon="cheveron-right" /%}](/docs/products/auth/magic-url)
[OAuth2 {% icon icon="cheveron-right" /%}](/docs/products/auth/oauth2)

View File

@@ -6,7 +6,7 @@ description: This is the description used for SEO.
Email and password login is the most commonly used authentication method. Appwrite Authentication promotes a safer internet by providing secure APIs and promoting better password choices to end users. Appwrite supports added security features like blocking personal info in passwords, password dictionary, and password history to help users choose good passwords. Email and password login is the most commonly used authentication method. Appwrite Authentication promotes a safer internet by providing secure APIs and promoting better password choices to end users. Appwrite supports added security features like blocking personal info in passwords, password dictionary, and password history to help users choose good passwords.
## Sign up {% #sign-up %} ## Signup {% #sign-up %}
You can use the Appwrite Client SDKs to create an account using email and password. You can use the Appwrite Client SDKs to create an account using email and password.
@@ -28,7 +28,7 @@ promise.then(function (response) {
}); });
``` ```
Passwords are hashed with [Argon2](#), a resilient and secure password hashing algorithm. Passwords are hashed with [Argon2](https://github.com/P-H-C/phc-winner-argon2), a resilient and secure password hashing algorithm.
## Verification {% #verification %} ## Verification {% #verification %}

View File

@@ -1,10 +1,10 @@
--- ---
layout: article layout: article
title: Server Integrations title: JWT login
description: This is the description used for SEO. description: This is the description used for SEO.
--- ---
You can extend Appwrite's APIs by building backend apps using [Server SDKs](#). To secure your backend app's APIs, client apps must prove their identity against your backend app before accessing sensitive information. You can secure these APIs and enforce access permissions in your backend app by using JWT authentication. You can extend Appwrite's APIs by building backend apps using [Server SDKs](/docs/sdks#server). To secure your backend app's APIs, client apps must prove their identity against your backend app before accessing sensitive information. You can secure these APIs and enforce access permissions in your backend app by using JWT authentication.
If you are already authenticated on your client-side app and need your backend app to **act on behalf of the user**, this guide will walk you through the process. If you are already authenticated on your client-side app and need your backend app to **act on behalf of the user**, this guide will walk you through the process.
@@ -20,7 +20,7 @@ When you build backend APIs to extend Appwrite's functionality, these APIs shoul
You need to create a session using the Client SDKs **before** generating a JWT. The JWT will be a stateless proof of claim for the identity of the authenticated user and expire after 15 minutes or when the session is deleted. You need to create a session using the Client SDKs **before** generating a JWT. The JWT will be a stateless proof of claim for the identity of the authenticated user and expire after 15 minutes or when the session is deleted.
You can generate a JWT like this: You can generate a JWT like this on a [Client SDK](/docs/sdks#client).
{% multicode %} {% multicode %}
```js ```js
@@ -79,6 +79,7 @@ mutation {
Your server application can use the JWT to act on behalf of the user by creating a `Client` instance with the JWT for **each request it receives**. To keep your API secure, **discard the client object** after each request. Your server application can use the JWT to act on behalf of the user by creating a `Client` instance with the JWT for **each request it receives**. To keep your API secure, **discard the client object** after each request.
Use JWTs tokens like this in a [Server SDK](/docs/sdks#server).
{% multicode %} {% multicode %}
```js ```js
const { Client } = require('node-appwrite'); const { Client } = require('node-appwrite');
@@ -364,7 +365,7 @@ Only Kevin's birthday is returned and documents where `user-A` has no permission
} }
``` ```
If the same request is made where the Server SDK's `client` is authenticated with an API key instead of a JWT, the results returned will be different. If the same request is made where the [Server SDK](/docs/sdks#server)'s `client` is authenticated with an API key instead of a JWT, the results returned will be different.
{% multicode %} {% multicode %}
```js ```js

View File

@@ -183,4 +183,4 @@ This would correspond with the permissions below.
| Delete | `Permissions.delete(Role.label('subscriber'))` | | Delete | `Permissions.delete(Role.label('subscriber'))` |
| Create | `Permissions.create(Role.label('subscriber'))` | | Create | `Permissions.create(Role.label('subscriber'))` |
[Learn more about permissions](/docs/advanced/platform/permissions) [Learn more about permissions {% icon icon="cheveron-right" /%}](/docs/advanced/platform/permissions)

View File

@@ -6,9 +6,9 @@ description: This is the description used for SEO.
Magic URL is a password-less way to authenticate users. When a user logs in by providing their email, they will receive an email with a "magic" link that contains a secret used to log in the user. The user can simply click the link to be logged in. Magic URL is a password-less way to authenticate users. When a user logs in by providing their email, they will receive an email with a "magic" link that contains a secret used to log in the user. The user can simply click the link to be logged in.
## Send Email {% #init %} ## Send email {% #init %}
Initialize the log in process with the [Create Magic URL Session](#) route. If the email has never been used, a **new account is generated**, then the user will receive an email. If the email is already attached to an account, the **user ID is ignored** and the user will receive a link in their email. Initialize the log in process with the [Create Magic URL Session](/docs/references/cloud/client-web/account#createMagicURLSession) route. If the email has never been used, a **new account is generated**, then the user will receive an email. If the email is already attached to an account, the **user ID is ignored** and the user will receive a link in their email.
{% multicode %} {% multicode %}
```js ```js

View File

@@ -22,7 +22,7 @@ Before using OAuth 2 login, you need to enable and configure an OAuth 2 login pr
## Initialize OAuth 2 login {% #init %} ## Initialize OAuth 2 login {% #init %}
To initialize the OAuth 2 login process, use the [Create OAuth 2 Session](#) route. To initialize the OAuth 2 login process, use the [Create OAuth 2 Session](/docs/references/cloud/client-web/account#createOAuth2Session) route.
{% tabs %} {% tabs %}
{% tabsitem #js title="Javascript" %} {% tabsitem #js title="Javascript" %}
@@ -234,7 +234,7 @@ You can use the `providerAccessToken` to make requests to your OAuth 2 provider.
## OAuth 2 profile {% #profile %} ## OAuth 2 profile {% #profile %}
OAuth 2 sessions expire to protect from security risks. OAuth 2 sessions should be refreshed periodically, so access tokens don't expire. Check value of `providerAccessTokenExpiry` to know if the token is expired or is about to expire. Refreshing before every request might cause rate limit problems. You can do this by calling the [Update OAuth Session](#) endpoint when ever your user visits your app. OAuth 2 sessions expire to protect from security risks. OAuth 2 sessions should be refreshed periodically, so access tokens don't expire. Check value of `providerAccessTokenExpiry` to know if the token is expired or is about to expire. Refreshing before every request might cause rate limit problems. You can do this by calling the [Update OAuth Session](/docs/references/cloud/client-web/account#updateSession) endpoint when ever your user visits your app.
{% multicode %} {% multicode %}
```js ```js
@@ -293,4 +293,6 @@ let session = try await account.updateSession(
{% /multicode %} {% /multicode %}
> **Note**: OAuth 2 is not available through the GraphQL API. You can use the REST API or any Client SDK instead. {% info title="GraphQL" %}
OAuth 2 is not available through the GraphQL API. You can use the REST API or any Client SDK instead.
{% /info %}

View File

@@ -1,12 +1,12 @@
--- ---
layout: article layout: article
title: Phone and SMS login title: Phone (SMS) login
description: This is the description used for SEO. description: This is the description used for SEO.
--- ---
Phone authentication lets users create accounts using their phone numbers and log in through SMS messages. Phone authentication lets users create accounts using their phone numbers and log in through SMS messages.
## [Send SMS Message](#init) {% #init %} ## Send SMS message {% #init %}
Phone authentication is done using a two-step authentication process. When using phone authentication, the authentication request is initiated from the client application and an SMS message is sent to the user's phone. The SMS message will contain a secret the user can use to log in. Phone authentication is done using a two-step authentication process. When using phone authentication, the authentication request is initiated from the client application and an SMS message is sent to the user's phone. The SMS message will contain a secret the user can use to log in.
@@ -97,7 +97,7 @@ mutation {
{% /multicode %} {% /multicode %}
## [Log In](#login) {% #login %} ## Login {% #login %}
After initiating the phone authentication process, the returned user ID and secret are used to confirm the user. The secret will usually be a 6-digit number in the SMS message sent to the user. After initiating the phone authentication process, the returned user ID and secret are used to confirm the user. The secret will usually be a 6-digit number in the SMS message sent to the user.

View File

@@ -10,7 +10,7 @@ Adding signup and login is as simple as this.
## Sign up {% #sign-up %} ## Sign up {% #sign-up %}
You can use the Appwrite Client SDKs to create an account using email and password. You can use the Appwrite [Client SDKs](/docs/sdks#client) to create an account using email and password.
{% multicode %} {% multicode %}
```js ```js
@@ -91,7 +91,7 @@ mutation {
## Login {% #login %} ## Login {% #login %}
After you've created your account, users can be logged in using the Create Email Session route. After you've created your account, users can be logged in using the [Create Email Session](/docs/references/cloud/client-web/account#createEmailSession) route.
{% multicode %} {% multicode %}
```js ```js

View File

@@ -10,15 +10,16 @@ Appwrite provides many security features to keep both your Appwrite project and
Appwrite handles the persistence of the session in a consistent way across SDKs. After authenticating with an SDK, the SDK will persist the session so that the user will not need to log in again the next time they open the app. The mechanism for persistence depends on the SDK. Appwrite handles the persistence of the session in a consistent way across SDKs. After authenticating with an SDK, the SDK will persist the session so that the user will not need to log in again the next time they open the app. The mechanism for persistence depends on the SDK.
> **Best Practice** {% info title="Best Practice" %}
> Only keep user sessions active as long as needed and maintain exactly **one** instance of the Client SDK in your app to avoid conflicting session data. Only keep user sessions active as long as needed and maintain exactly **one** instance of the Client SDK in your app to avoid conflicting session data.
{% /info %}
| | Framework | Storage method | | {% width=70 %} | Framework {% width=120 %} | Storage method |
|:----------------------------------------------------------------------------------------------------:|:---:|:----------------------------------------------------------------------------------------------------------------------:| |:----------------------------------------------------------------------------------------------------:|:---:|:----------------------------------------------------------------------------------------------------------------------:|
| [TODO] | Web | Uses a secure session cookie and falls back to local storage when a session cookie is not available. | | {% only_dark %}{% icon_image src="/images/platforms/dark/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Web | Uses a secure session cookie and falls back to local storage when a session cookie is not available. |
| [TODO] | Flutter | Uses a session cookie stored in Application Documents through the **path_provider** package. | | {% only_dark %}{% icon_image src="/images/platforms/dark/flutter.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/flutter.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Flutter | Uses a session cookie stored in Application Documents through the **path_provider** package. |
| [TODO] | Apple | Uses a session cookie stored in **UserDefaults**. | | {% only_dark %}{% icon_image src="/images/platforms/dark/apple.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/apple.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Apple | Uses a session cookie stored in **UserDefaults**. |
| [TODO] | Android | Uses a session cookie stored in **SharedPreferences**. | | {% only_dark %}{% icon_image src="/images/platforms/dark/android.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/android.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Android | Uses a session cookie stored in **SharedPreferences**. |
## Session limits ## Session limits
In Appwrite versions 1.2 and above, you can limit the number of active sessions created per user to prevent the accumulation of unused but active sessions. New sessions created by the same user past the session limit delete the oldest session. In Appwrite versions 1.2 and above, you can limit the number of active sessions created per user to prevent the accumulation of unused but active sessions. New sessions created by the same user past the session limit delete the oldest session.

View File

@@ -5,10 +5,10 @@ description: This is the description used for SEO.
--- ---
Teams are a good way to allow users to share access to resources. Teams are a good way to allow users to share access to resources.
For example, in a todo app, a user can [create a team](#) for one of their todo lists and [invite another user](#) to the team to grant the other user access. For example, in a todo app, a user can [create a team](/docs/references/cloud/client-web/teams#create) for one of their todo lists and [invite another user](/docs/references/cloud/client-web/teams#createMembership) to the team to grant the other user access.
You can further give special rights to parts of a team using team roles. You can further give special rights to parts of a team using team roles.
The invited user can [accept the invitation](#) to gain access. If the user's ever removed from the team, they'll lose access again. The invited user can [accept the invitation](/docs/references/cloud/client-web/teams#updateMembershipStatus) to gain access. If the user's ever removed from the team, they'll lose access again.
## Create team {% #create %} ## Create team {% #create %}
For example, we can create a team called `teachers` with roles `maths`, `sciences`, `arts`, and `literature`. For example, we can create a team called `teachers` with roles `maths`, `sciences`, `arts`, and `literature`.
@@ -195,4 +195,7 @@ individual roles in the team using the `Role.team(<TEAM_ID>, [<ROLE_1>, <ROLE_2>
| Description | Role | | Description | Role |
| ------------------------------------------- | ------------------------------------------- | | ------------------------------------------- | ------------------------------------------- |
| All members | `Role.team(<TEAM_ID>)`| | All members | `Role.team(<TEAM_ID>)`|
| Select roles | `Role.team(<TEAM_ID>, [<ROLE_1>, <ROLE_2>, ...])`| | Select roles | `Role.team(<TEAM_ID>, [<ROLE_1>, <ROLE_2>, ...])`|
[Learn more about permissions {% icon icon="cheveron-right" /%}](/docs/advanced/platform/permissions)

View File

@@ -0,0 +1,15 @@
---
layout: article
title: Manage users
description: This is the description used for SEO.
---
Appwrite Users API is used for managing users in server applications.
Users API can only be used with an API key with the [Server SDK](/docs/sdks#server), to manage all users.
If you need to act on behalf of users through an Appwrite Function or your own backend, use [JWT login](/docs/products/auth/jwt).
{% partial file="account-vs-user.md" /%}
The users API can be used to create users, import users, update user info, get user audit logs, and remove users.
[Learn more in the Users API references {% icon icon="cheveron-right" /%}](/docs/references/cloud/server-nodejs/users)

View File

@@ -62,7 +62,16 @@
href: '/docs/products/databases/pagination' href: '/docs/products/databases/pagination'
} }
] ]
} },
{
label: 'References',
items: [
{
label: 'Databases API',
href: '/docs/references/cloud/client-web/databases'
},
]
},
]; ];
</script> </script>

View File

@@ -1,6 +1,6 @@
--- ---
layout: article layout: article
title: Databases title: Overview
description: This is the description used for SEO. description: This is the description used for SEO.
--- ---
@@ -14,4 +14,4 @@ Databases store data, if you need to store files like images, PDFs or videos, us
You can organize data into databases, collections, and documents. You can also paginate, order, and query documents. You can organize data into databases, collections, and documents. You can also paginate, order, and query documents.
For complex business logic, Appwrite supports relationships to help you model your data. For complex business logic, Appwrite supports relationships to help you model your data.
[Quick start {% icon icon="cheveron-right" /%}](#) [Quick start {% icon icon="cheveron-right" /%}](/docs/products/databases/quick-start)

View File

@@ -11,15 +11,15 @@ The terms collections and documents are used because the Appwrite JSON REST API
That said, Appwrite is designed to support both SQL and NoSQL database adapters like MariaDB, MySQL, or MongoDB in future versions. That said, Appwrite is designed to support both SQL and NoSQL database adapters like MariaDB, MySQL, or MongoDB in future versions.
## Create collection ## Create collection
You can create collections using the Appwrite Console or a [Server SDK](#). You can create collections using the Appwrite Console or a [Server SDK](/docs/sdks#server).
{% tabs %} {% tabs %}
{% tabsitem #console title="Console" %} {% tabsitem #console title="Console" %}
You can create a collection by heading to the **Databases** page, navigate to a [database](#), and click **Create collection**. You can create a collection by heading to the **Databases** page, navigate to a [database](/docs/products/databases/databases), and click **Create collection**.
{% /tabsitem %} {% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %} {% tabsitem #server-sdk title="Server SDK" %}
You can also create collections programmatically using a [Server SDK](#). Appwrite [Server SDKs](#) require an [API key](#). You can also create collections programmatically using a [Server SDK](/docs/sdks#server). Appwrite [Server SDKs](/docs/sdks#server) require an [API key](/docs/advanced/platform/api-keys).
{% multicode %} {% multicode %}
@@ -223,7 +223,7 @@ let collection = try await databases.createCollection(
``` ```
{% /multicode %} {% /multicode %}
You can also configure **permissions** in the `createCollection` method, learn more about the `createCollection` in the [API references](#). You can also configure **permissions** in the `createCollection` method, learn more about the `createCollection` in the [API references](/docs/references).
{% /tabsitem %} {% /tabsitem %}
{% /tabs %} {% /tabs %}
@@ -254,7 +254,7 @@ You can choose between the following types.
| `ip` | IP address attribute for IPv4 and IPv6. | | `ip` | IP address attribute for IPv4 and IPv6. |
| `email` | Email address attribute. | | `email` | Email address attribute. |
| `url` | URL attribute. | | `url` | URL attribute. |
| `relationship` | Relationship attribute relates one collection to another. [Learn more about relationships.](#) | | `relationship` | Relationship attribute relates one collection to another. [Learn more about relationships.](/docs/products/databases) |
If an attribute must be populated in all documents, set it as `required`. If an attribute must be populated in all documents, set it as `required`.
If not, you may optionally set a default value. If not, you may optionally set a default value.
@@ -272,6 +272,6 @@ The following indexes are currently supported:
|------------|--------------------------------------------------------------------------------------------------------------| |------------|--------------------------------------------------------------------------------------------------------------|
| `key` | Plain Index to allow queries. | | `key` | Plain Index to allow queries. |
| `unique` | Unique Index to disallow duplicates. | | `unique` | Unique Index to disallow duplicates. |
| `fulltext` | For searching within string attributes. Required for the [search query method](#). | | `fulltext` | For searching within string attributes. Required for the [search query method](/docs/products/databases/queries#query-class). |
You can create an index by navigating to your collection's **Indexes** tab or by using your favorite [Server SDK](#). You can create an index by navigating to your collection's **Indexes** tab or by using your favorite [Server SDK](/docs/sdks#server).

View File

@@ -16,7 +16,7 @@ You can create a database by navigating to the **Databases** page and clicking *
## Create a database using Server SDKs ## Create a database using Server SDKs
You can programmatically create databases using a [Server SDK](#). Appwrite [Server SDKs](#) require an [API key](#). You can programmatically create databases using a [Server SDK](/docs/sdks#server). Appwrite [Server SDKs](/docs/sdks#server) require an [API key](/docs/advanced/platform/api-keys).
{% multicode %} {% multicode %}
```js ```js

View File

@@ -135,7 +135,7 @@ You must grant **read** permissions to users at the **collection level** before
[Learn more about permissions](#permissions) [Learn more about permissions](#permissions)
{% /info %} {% /info %}
Documents can be retrieved using the [List Document](#) endpoint. Documents can be retrieved using the [List Document](/docs/references/cloud/client-web/databases#listDocuments) endpoint.
Results can be filtered, sorted, and paginated using Appwrite's shared set of query methods. Results can be filtered, sorted, and paginated using Appwrite's shared set of query methods.
You can find a full guide on querying in the [Queries Guide](/docs/products/databases/queries). You can find a full guide on querying in the [Queries Guide](/docs/products/databases/queries).

View File

@@ -7,11 +7,11 @@ readtime: 5
--- ---
You can order results returned by Appwrite Databases by using an order query. You can order results returned by Appwrite Databases by using an order query.
For best performance, create an [index](#) on the column you plan to order by. For best performance, create an [index](/docs/products/databases/collections#indexes) on the column you plan to order by.
## Ordering one column {% #one-column %} ## Ordering one column {% #one-column %}
When querying using the [listDocuments](#) endpoint, When querying using the [listDocuments](/docs/references/cloud/client-web/databases#listDocuments) endpoint,
you can specify the order of the documents returned using the `Query.orderAsc()` and `Query.orderDesc()` query methods. you can specify the order of the documents returned using the `Query.orderAsc()` and `Query.orderDesc()` query methods.
{% multicode %} {% multicode %}

View File

@@ -19,7 +19,7 @@ If a user has read, create, update, or delete permissions at the collection leve
Configure collection level permissions by navigating to **Your collection** > **Settings** > **Permissions**. Configure collection level permissions by navigating to **Your collection** > **Settings** > **Permissions**.
[Learn more about permissions and roles](#) [Learn more about permissions and roles](/docs/advanced/platform/permissions)
## Document level {% #document-level %} ## Document level {% #document-level %}
Document level permissions grant access to individual documents. Document level permissions grant access to individual documents.
@@ -28,8 +28,8 @@ If a user has read, create, update, or delete permissions at the document level,
Document level permissions are only applied if Document Security is enabled in the settings of your collection. Document level permissions are only applied if Document Security is enabled in the settings of your collection.
Enable document level permissions by navigating to **Your collection** > **Settings** > **Document security**. Enable document level permissions by navigating to **Your collection** > **Settings** > **Document security**.
Document level permissions are configured in individual [documents](#). Document level permissions are configured in individual documents.
[Learn more about permissions and roles](#) [Learn more about permissions and roles](/docs/advanced/platform/permissions)

View File

@@ -26,13 +26,13 @@ Appwrite SDKs provide a `Query` class to help you build queries. The `Query` cla
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. | | `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. | | `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. | | `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [Full-text index](#) on queried attributes. | | `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. | | `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. | | `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](#). If the limit query is not used, the limit defaults to 25 results. | | `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](#). | | `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](#). | | `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](#). | | `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
## Building Queries {% #building-queries %} ## Building Queries {% #building-queries %}

View File

@@ -63,7 +63,7 @@ Appwrite also allows you to define the behavior of a relationship when a documen
| Set null | If a document has related documents, when it is deleted, the related documents are kept with their relationship attribute set to null.| | Set null | If a document has related documents, when it is deleted, the related documents are kept with their relationship attribute set to null.|
## Creating relationships {% #create-relationships %} ## Creating relationships {% #create-relationships %}
You can define relationships in the Appwrite Console, or using a [Server SDK](#) You can define relationships in the Appwrite Console, or using a [Server SDK](/docs/sdks#server)
{% tabs %} {% tabs %}
{% tabsitem #console title="Console" %} {% tabsitem #console title="Console" %}
@@ -616,7 +616,6 @@ databases.updateDocument(
{% /multicode %} {% /multicode %}
## Delete relationships {% #delete %} ## Delete relationships {% #delete %}
[TODO WHY ARE H2 and H3 same sizee]
### Unlink relationships, retain documents {% #unlink %} ### Unlink relationships, retain documents {% #unlink %}
If you need to unlink documents in a relationship but retain the documents, you can do this by **updating the relationship attribute** and removing the ID of the related document. If you need to unlink documents in a relationship but retain the documents, you can do this by **updating the relationship attribute** and removing the ID of the related document.

View File

@@ -22,7 +22,7 @@
] ]
}, },
{ {
label: 'Guides', label: 'Journeys',
items: [ items: [
{ {
label: 'Development', label: 'Development',
@@ -45,7 +45,16 @@
href: '/docs/products/functions/examples' href: '/docs/products/functions/examples'
} }
] ]
} },
{
label: 'References',
items: [
{
label: 'Functions API',
href: '/docs/references/cloud/client-web/functions'
},
]
},
]; ];
</script> </script>

View File

@@ -1,6 +1,6 @@
--- ---
layout: article layout: article
title: Functions title: Overview
description: [TODO] description: [TODO]
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3

View File

@@ -40,8 +40,9 @@ Before deploying your function with Git, create a new function attached to your
## CLI {% #cli %} ## CLI {% #cli %}
> ### CLI Setup {% #cli-setup %} {% info title="CLI setup" %}
> Before you can deploy with the Appwrite CLI, make sure you've [installed and initialized](#) the CLI. Before you can deploy with the Appwrite CLI, make sure you've [installed and initialized](/docs/tooling/command-line/installation) the CLI.
{% /info %}
To deploy with the Appwrite CLI, your function must be added to `appwrite.json`. Use the `appwrite init function` method to create a starter function, then paste in your function code. To deploy with the Appwrite CLI, your function must be added to `appwrite.json`. Use the `appwrite init function` method to create a starter function, then paste in your function code.

View File

@@ -419,10 +419,10 @@ You'll find these properties in the context object.
| Property | Description | | Property | Description |
|----------|--------------------------------------------------------------------------------------------------------------------------| |----------|--------------------------------------------------------------------------------------------------------------------------|
| req | Contains request information like method, body, and headers. See full examples [here](#). | | req | Contains request information like method, body, and headers. See full examples [in the request section](#request). |
| res | Contains methods to build a response and return information. See full examples [here](#). | | res | Contains methods to build a response and return information. See full examples [in the response section](#response). |
| log() | Method to log information to the Appwrite Console, end users will not be able to see these logs. See full examples [here](#). | | log() | Method to log information to the Appwrite Console, end users will not be able to see these logs. See full examples [in the logging section](#logging). |
| error() | Methoc to log errors to the Appwrite Console, end users will not be able to see these errors. See full examples [here](#). | | error() | Methoc to log errors to the Appwrite Console, end users will not be able to see these errors. See full examples [in the logging section](#logging). |
#### Destructuring assignment {% #destructuring %} #### Destructuring assignment {% #destructuring %}
Some languages, namely JavaScript, support destructuring. Some languages, namely JavaScript, support destructuring.
@@ -683,7 +683,7 @@ These are provided alongside any custom headers sent to the function.
| `x-appwrite-trigger` | Describes how the function execution was invoked. Possible values are `http`, `schedule` or `event`. | | `x-appwrite-trigger` | Describes how the function execution was invoked. Possible values are `http`, `schedule` or `event`. |
| `x-appwrite-event` | If the function execution was triggered by an event, describes the triggering event. | | `x-appwrite-event` | If the function execution was triggered by an event, describes the triggering event. |
| `x-appwrite-user-id` | If the function execution was invoked by an authenticated user, display the user ID. This doesn't apply to Appwrite Console users or API keys. | | `x-appwrite-user-id` | If the function execution was invoked by an authenticated user, display the user ID. This doesn't apply to Appwrite Console users or API keys. |
| `x-appwrite-user-jwt` | JWT token generated from the invoking user's session. Used to authenticate Server SDKs to respect access permissions. [Learn more about JWT tokens](#). | | `x-appwrite-user-jwt` | JWT token generated from the invoking user's session. Used to authenticate Server SDKs to respect access permissions. [Learn more about JWT tokens](/docs/products/auth/jwt). |
| `x-appwrite-country-code` | Displays the country code of the configured locale. | | `x-appwrite-country-code` | Displays the country code of the configured locale. |
| `x-appwrite-continent-code` | Displays the continent code of the configured locale. | | `x-appwrite-continent-code` | Displays the continent code of the configured locale. |
| `x-appwrite-continent-eu` | Describes if the configured local is within the EU. | | `x-appwrite-continent-eu` | Describes if the configured local is within the EU. |
@@ -928,7 +928,7 @@ namespace runtime {
``` ```
{% /multicode %} {% /multicode %}
To get the different response types, set one of the following query parameters in the [generated domain](#) of your function. To get the different response types, set one of the following query parameters in the [generated domain](/docs/products/functions/deployment#domains) of your function.
| Type | Query Param | Example | | Type | Query Param | Example |
|----------|-----------------|-------------------------------------------------------------| |----------|-----------------|-------------------------------------------------------------|
@@ -1088,12 +1088,13 @@ You can access these logs through the following steps.
3. Under the Executions tab, click on an execution. 3. Under the Executions tab, click on an execution.
4. In the Response section, you'll be able to view logs under the Logs and Errors tabs. 4. In the Response section, you'll be able to view logs under the Logs and Errors tabs.
## Accessing Environment Variables {% #environment-variables %} ## Accessing environment variables {% #environment-variables %}
If you need to pass constants or secrets to Appwrite Functions, you can use environment variables. If you need to pass constants or secrets to Appwrite Functions, you can use environment variables.
Environmental variables can be global, or function-specific. Environmental variables can be global, or function-specific.
> ### Appwrite API keys {% info title="Appwrite API keys" %}
> If your function is using an Appwrite SDK with an API key, this API key needs to be generated and passed in manually. API keys are not passed by default for security reasons. If your function is using an Appwrite SDK with an API key, this API key needs to be generated and passed in manually. API keys are not passed by default for security reasons.
{% /info %}
| Variable | Description | | Variable | Description |
|-----------------------------------|------------------------------------------------| |-----------------------------------|------------------------------------------------|
@@ -1218,28 +1219,89 @@ namespace runtime {
## Dependencies {% #dependencies %} ## Dependencies {% #dependencies %}
Your function's dependencies should be managed by the package manager of each language. Your function's dependencies should be managed by the package manager of each language.
By default, we include the following package managers in each runtime. By default, we include the following package managers in each runtime.
| Language | Package Manager | Commands | |
|----------|-----------------|-----------------------|------------------------------------| {% table %}
| [TODO] | Node.js | npm | npm install | * &nbsp; {% width=80 %}
| [TODO] | PHP | Composer | composer install | * Language
| [TODO] | Python | pip | pip install -r requirements.txt | * Package Manager
| [TODO] | Ruby | Bundler | bundle install | * Commands
| [TODO] | Deno | deno | deno cache <ENTRYPOINT_FILE> | ---
| [TODO] | Dart | pub | pub get | * {% only_dark %}{% icon_image src="/images/platforms/dark/nodejs.svg" alt="Node.js logo" size="m" /%}{% /only_dark %}
| [TODO] | Swift | Swift Package Manager | swift package resolve | {% only_light %}{% icon_image src="/images/platforms/nodejs.svg" alt="Node.js logo" size="m" /%}{% /only_light %}
| [TODO] | .NET | NuGet | dotnet restore | * Node.js
| [TODO] | Kotlin | Gradle | N/A | * NPM
| [TODO] | Java | Gradle | N/A | * `npm install`
| [TODO] | C++ | None | N/A | ---
* {% only_dark %}{% icon_image src="/images/platforms/dark/php.svg" alt="PHP logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/php.svg" alt="PHP logo" size="m" /%}{% /only_light %}
* PHP
* Composer
* `composer install`
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/python.svg" alt="Python logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/python.svg" alt="Python logo" size="m" /%}{% /only_light %}
* Python
* pip
* `pip install -r requirements.txt`
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/ruby.svg" alt="Ruby logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/ruby.svg" alt="Ruby logo" size="m" /%}{% /only_light %}
* Ruby
* Bundler
* bundle install
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/deno.svg" alt="Deno logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/deno.svg" alt="Deno logo" size="m" /%}{% /only_light %}
* Deno
* deno
* `deno cache <ENTRYPOINT_FILE>`
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/dart.svg" alt="Dart logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/dart.svg" alt="Dart logo" size="m" /%}{% /only_light %}
* Dart
* pub
* `pub get`
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/swift.svg" alt="Swift logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/swift.svg" alt="Swift logo" size="m" /%}{% /only_light %}
* Swift
* Swift Package Manager
* `swift package resolve`
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/dotnet.svg" alt=".NET logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/dotnet.svg" alt=".NET logo" size="m" /%}{% /only_light %}
* .NET
* NuGet
* `dotnet restore`
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/kotlin.svg" alt="Kotlin logo" size="m" /%}{% /only_light %}
* Kotlin
* Gradle
* N/A
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/java.svg" alt="Java logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/java.svg" alt="Java logo" size="m" /%}{% /only_light %}
* Java
* Gradle
* N/A
---
* {% only_dark %}{% icon_image src="/images/platforms/dark/c.svg" alt="C++ logo" size="m" /%}{% /only_dark %}
{% only_light %}{% icon_image src="/images/platforms/c.svg" alt="C++ logo" size="m" /%}{% /only_light %}
* C++
* None
* N/A
{% /table %}
To install your dependencies before your function is built, you should add the relevant install command to the top your function's **Build setting** > **Commands**. To install your dependencies before your function is built, you should add the relevant install command to the top your function's **Build setting** > **Commands**.
## Using Appwrite in a function {% #using-appwrite %} ## Using Appwrite in a function {% #using-appwrite %}
Appwrite can be used in your functions by adding the relevant SDK to your function's dependencies. Appwrite can be used in your functions by adding the relevant SDK to your function's dependencies.
Authenticating with Appwrite is done via an API key or a JWT token. Authenticating with Appwrite is done via an API key or a JWT token.
API keys must be generated and exported as an [environment variable](#). API keys must be generated and exported as an [environment variable](/docs/advanced/self-hosting/environment-variables).
You can read more about authentication in the [Server authentication](#) section of the docs. You can read more about authentication in the [JWT login](/docs/products/auth/jwt) section of the docs.
### Using with API key {% #using-api-key %} ### Using with API key {% #using-api-key %}
API keys have defined scopes when you create them. API keys have defined scopes when you create them.
@@ -2124,10 +2186,10 @@ You will have to migrate your old functions to follow new runtime syntax.
Here's a checklist of things you need to know. Here's a checklist of things you need to know.
1. The parameter passed into functions has changed. `req` and `res` has been replaced by `context`, which contains new logger methods. [Learn about context](#). 1. The parameter passed into functions has changed. `req` and `res` has been replaced by `context`, which contains new logger methods. [Learn about context](/docs/products/functions/development#context-object).
2. To improve privacy and logging reliability, we provide new `context.log()` and `context.error()` functions. You can no longer use native logging methods. [Learn about logging](#). 2. To improve privacy and logging reliability, we provide new `context.log()` and `context.error()` functions. You can no longer use native logging methods. [Learn about logging](/docs/products/functions/development#logging).
3. The old way of `req.variables` has been deprecated. You can now access variables passed into each function as environment variables. [Learn about environment variables](#). 3. The old way of `req.variables` has been deprecated. You can now access variables passed into each function as environment variables. [Learn about environment variables](/docs/products/functions/development#environment-variables).
4. The `req` object has been updated to use terminology consistent with typical HTTP concepts. You'll now find familiar concepts like headers, body, HTTP methods, and others. [Learn about request](#). 4. The `req` object has been updated to use terminology consistent with typical HTTP concepts. You'll now find familiar concepts like headers, body, HTTP methods, and others. [Learn about request](/docs/products/functions/development#request).
5. The response object has been updated. You can now specify headers, as well as use new methods like return redirects or empty responses. [Learn about response](#). 5. The response object has been updated. You can now specify headers, as well as use new methods like return redirects or empty responses. [Learn about response](/docs/products/functions/development#response).
6. Now, you must return a response such as return `context.res.send("")`. This prevents confusing errors when functions are terminated prematurely before a response is sent. [Learn about response](#). 6. Now, you must return a response such as return `context.res.send("")`. This prevents confusing errors when functions are terminated prematurely before a response is sent. [Learn about response](/docs/products/functions/development#response).
7. Some variables about how a function was triggered are now found in the context.req object as headers. 7. Some variables about how a function was triggered are now found in the context.req object as headers.

View File

@@ -35,7 +35,7 @@
] ]
}, },
{ {
label: 'Guides', label: 'Journeys',
items: [ items: [
{ {
label: 'Upload and download', label: 'Upload and download',
@@ -46,7 +46,16 @@
href: '/docs/products/storage/images' href: '/docs/products/storage/images'
}, },
] ]
} },
{
label: 'References',
items: [
{
label: 'Storage API',
href: '/docs/references/cloud/client-web/storage'
},
]
},
]; ];
</script> </script>

View File

@@ -1,6 +1,6 @@
--- ---
layout: article layout: article
title: Storage title: Overview
description: This is the description used for SEO. description: This is the description used for SEO.
difficulty: beginner difficulty: beginner
readtime: 5 readtime: 5

View File

@@ -10,7 +10,7 @@ Storage buckets are a group of files, similar to collections in Appwrite Databas
Buckets let you limit file size and extensions, whether or not to encrypt the files, and more. Buckets let you limit file size and extensions, whether or not to encrypt the files, and more.
## Create Bucket ## Create Bucket
You can create your bucket from the Appwrite Console or a [Server SDK](#). You can create your bucket from the Appwrite Console or a [Server SDK](/docs/sdks#server).
{% tabs %} {% tabs %}
{% tabsitem #console title="Console" %} {% tabsitem #console title="Console" %}
@@ -19,7 +19,7 @@ You can create a bucket by heading to the **Storage** page and clicking **Create
{% /tabsitem %} {% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %} {% tabsitem #server-sdk title="Server SDK" %}
You can also create collections programmatically using a [Server SDK](#). Appwrite [Server SDKs](#) require an [API key](#). You can also create collections programmatically using a [Server SDK](/docs/sdks#server). Appwrite [Server SDKs](/docs/sdks#server) require an [API key](/docs/advanced/platform/api-keys).
{% multicode %} {% multicode %}
@@ -219,7 +219,7 @@ let bucket = try await storage.createBucket(
``` ```
{% /multicode %} {% /multicode %}
You can also configure permission, file size and extension restrictions, and more in the `createBucket` method, learn more about the `createBucket` in the [API references](#). You can also configure permission, file size and extension restrictions, and more in the `createBucket` method, learn more about the `createBucket` in the [API references](/docs/references/cloud/server-nodejs/storage#createBucket).
{% /tabsitem %} {% /tabsitem %}
{% /tabs %} {% /tabs %}

View File

@@ -10,7 +10,7 @@ Appwrite provides utilities to manipulate images for previewing images in your a
## Image manipulation {% #image-manupulation %} ## Image manipulation {% #image-manupulation %}
Appwrite Storage's [preview endpoint](#) let you manipulate resolution, add borders and the border-radius, add background-color, set the opacity for the image, and get the image in the appropriate output format. Appwrite Storage's [preview endpoint](/docs/references/cloud/client-web/storage#getFilePreview) let you manipulate resolution, add borders and the border-radius, add background-color, set the opacity for the image, and get the image in the appropriate output format.
You can manipulate images resolution to display appropriately on responsive websites. You can also adjust the image border, background color, and border-radius to match the theming of your application. You can manipulate images resolution to display appropriately on responsive websites. You can also adjust the image border, background color, and border-radius to match the theming of your application.
The Appwrite Storage also allows you to change the format and compression of your images for network transfer optimization and to help you speed your application. You can do all that without caring about how the image was originally uploaded. The Appwrite Storage also allows you to change the format and compression of your images for network transfer optimization and to help you speed your application. You can do all that without caring about how the image was originally uploaded.
@@ -37,7 +37,7 @@ Below you can find all the different parameters offered by the preview endpoint
| output | Set the output image format. If not provided, will use the original image's format. Supported formats are: `jpg`, `jpeg`, `png`, `gif`, and `webp` | | output | Set the output image format. If not provided, will use the original image's format. Supported formats are: `jpg`, `jpeg`, `png`, `gif`, and `webp` |
## Examples {% #examples %} ## Examples {% #examples %}
Here are some examples using [Client SDKs](#). Here are some examples using [Client SDKs](/docs/sdks#client).
{% multicode %} {% multicode %}
```js ```js
import { Client, Storage } from "appwrite"; import { Client, Storage } from "appwrite";

View File

@@ -19,7 +19,7 @@ If a user has read, create, update, or delete permissions at the bucket level, t
Configure bucket level permissions by navigating to **Your bucket** > **Settings** > **Permissions**. Configure bucket level permissions by navigating to **Your bucket** > **Settings** > **Permissions**.
[Learn more about permissions and roles](#) [Learn more about permissions and roles](/docs/advanced/platform/permissions)
## File level {% #file-level %} ## File level {% #file-level %}
File level permissions grant access to individual files. File level permissions grant access to individual files.
@@ -28,8 +28,8 @@ If a user has read, create, update, or delete permissions at the file level, the
File level permissions are only applied if File Security is enabled in the settings of your bucket. File level permissions are only applied if File Security is enabled in the settings of your bucket.
Enable file level permissions by navigating to **Your bucket** > **Settings** > **File security**. Enable file level permissions by navigating to **Your bucket** > **Settings** > **File security**.
File level permissions are configured in individual [files](#). File level permissions are configured in individual [files](/docs/products/storage/permissions#file-level).
[Learn more about permissions and roles](#) [Learn more about permissions and roles](/docs/advanced/platform/permissions)

View File

@@ -127,7 +127,7 @@ To do so, navigate to the **Documents** tab of your collection and click the **A
## Large files {% #large-files %} ## Large files {% #large-files %}
When you are trying to upload any files above 5MB, you will need to upload them in chunks for better reliability and performance. When you are trying to upload any files above 5MB, you will need to upload them in chunks for better reliability and performance.
If you're using an Appwrite SDK, this is handled automatically. If you're using an Appwrite SDK, this is handled automatically.
If you're not using an SDK, you can [learn more about REST API file handling](#). If you're not using an SDK, you can [learn more about REST API file handling](/docs/apis/rest#files).
## InputFile {% #input-file %} ## InputFile {% #input-file %}
Every language and platform handles file inputs differently. This section documents the expected input type of each SDK. Where applicable, Appwrite provides an `InputFile` class to accept multiple file sources, like paths, buffers, streams, or plain text. Every language and platform handles file inputs differently. This section documents the expected input type of each SDK. Where applicable, Appwrite provides an `InputFile` class to accept multiple file sources, like paths, buffers, streams, or plain text.

View File

@@ -18,7 +18,7 @@
title: 'Web App', title: 'Web App',
quickStarts: [ quickStarts: [
{ {
title: 'Next.js', title: 'React.js',
icon: 'icon-next_js', icon: 'icon-next_js',
image: '/images/blog/placeholder.png', image: '/images/blog/placeholder.png',
href: 'nextjs' href: 'nextjs'
@@ -35,24 +35,6 @@
image: '/images/blog/placeholder.png', image: '/images/blog/placeholder.png',
href: 'sveltekit' href: 'sveltekit'
}, },
{
title: 'Nuxt',
icon: 'icon-nuxt_js',
image: '/images/blog/placeholder.png',
href: 'nuxt'
},
{
title: 'Angular',
icon: 'icon-angular',
image: '/images/blog/placeholder.png',
href: 'angular'
},
{
title: 'Astro',
icon: 'icon-astro',
image: '/images/blog/placeholder.png',
href: 'astro'
}
] ]
}, },
{ {
@@ -64,6 +46,12 @@
image: '/images/blog/placeholder.png', image: '/images/blog/placeholder.png',
href: 'flutter' href: 'flutter'
}, },
{
title: 'Apple',
icon: 'icon-apple',
image: '/images/blog/placeholder.png',
href: 'apple'
},
{ {
title: 'Android', title: 'Android',
icon: 'icon-android', icon: 'icon-android',
@@ -74,7 +62,32 @@
}, },
{ {
title: 'Server', title: 'Server',
quickStarts: [] quickStarts: [
{
title: 'Node.js',
icon: 'icon-node',
image: '/images/blog/placeholder.png',
href: 'node'
},
// {
// title: 'Python',
// icon: 'icon-python',
// image: '/images/blog/placeholder.png',
// href: 'python'
// },
// {
// title: '.NET',
// icon: 'icon-dotnet',
// image: '/images/blog/placeholder.png',
// href: 'dotnet'
// },
// {
// title: 'Dart',
// icon: 'icon-dart',
// image: '/images/blog/placeholder.png',
// href: 'dart'
// }
]
} }
]; ];
</script> </script>

View File

@@ -1,56 +1,242 @@
--- ---
layout: article layout: article
title: Quick start with Android title: Start with Android
description: Learn how to quickly integrate Appwrite products and services into your Android project. description: Learn how to quickly integrate Appwrite products and services into your Android project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3
--- ---
Learn to setup your first Apple project powered by Appwrite. Learn to setup your first Android project powered by Appwrite.
{% section #step-1 step=1 title="Create project" %}
{% section #step-1 step=1 title="Create Android project" %}
Open Android Studio and click **New Project** to create a new project.
Choose your desired project template and click **Next**.
Now enter your app **name** and **package name**. You will need both of these later when you create your project in the Appwrite console. Click **Finish** to create your project.
{% /section %}
{% section #step-2 step=2 title="Create Appwrite project" %}
Head to the [Appwrite Console](https://cloud.appwrite.io/console). Head to the [Appwrite Console](https://cloud.appwrite.io/console).
![Create project screen](/images/docs/databases/quick-start/create-project.png) ![Create project screen](/images/docs/databases/quick-start/create-project.png)
If this is your first time using Appwrite, create an accout and create your first project. If this is your first time using Appwrite, create an accout and create your first project.
Then, under **Add a platform**, add a **Android app** with the **Name** `My Application` and **Package name** `com.example.myapplication`. Then, under **Add a platform**, add an **Android app**.
Add your app's **name** and **package name**, your package name is the one entered when creating an Android project. For existing projects, you should use the **applicationId** in your app-level [build.gradle](https://github.com/appwrite/playground-for-android/blob/master/app/build.gradle#L11) file.
![Add a platform](/images/docs/databases/quick-start/add-platform.png) ![Add a platform](/images/docs/databases/quick-start/add-platform.png)
You can skip optional steps. You can skip optional steps.
{% /section %} {% /section %}
{% section #step-2 step=2 title="Create Android project" %}
Open Android Studios and click **New Project**, select **Empty Activity**. {% section #step-3 step=3 title="Add the Appwrite SDK" %}
**Name** the project `My Application` with **Package Name** `com.example.myapplication`. To add the Appwrite SDK for Android as a dependency, add the following to your app-level **build.gradle.kts** file inside the **dependencies** block.
```kotlin
implementation("io.appwrite:sdk-for-android:4.0.0")
```
In order to allow creating OAuth sessions, the following activity needs to be added inside the `<application>` tag, along side the existing `<activity>` tags in your [AndroidManifest.xml](https://github.com/appwrite/playground-for-flutter/blob/master/android/app/src/main/AndroidManifest.xml).
Be sure to replace the **[PROJECT_ID]** string with your actual Appwrite project ID.
You can find your Appwrite project ID in you project settings screen in your Appwrite Console.
```xml
<manifest ...>
...
<application ...>
...
<!-- Add this inside the `<application>` tag, along side the existing `<activity>` tags -->
<activity android:name="io.appwrite.views.CallbackActivity" android:exported="true">
<intent-filter android:label="android_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appwrite-callback-[PROJECT_ID]" />
</intent-filter>
</activity>
</application>
</manifest>
```
{% /section %} {% /section %}
{% section #step-3 step=3 title="Install Appwrite" %} {% section #step-4 step=4 title="Create Appwrite Singleton" %}
Install the Appwrite SDK for Android.
{% /section %}
{% section #step-4 step=4 title="Import Appwrite" %}
Find your project's ID in the **Settings** page. Find your project's ID in the **Settings** page.
![Settings page in Appwrite Console.](/images/docs/databases/quick-start/project-id.png) ![Settings page in Appwrite Console.](/images/docs/databases/quick-start/project-id.png)
Create a new file `src/lib/appwrite.js` and add the following code to it, replace `<YOUR_PROJECT_ID>` with your project ID. Create a new file `Appwrite.kt` and add the following code to it, replacing `[YOUR_PROJECT_ID]` with your project ID.
```swift ```kotlin
TODO package com.example.myapplication
import android.content.Context
import io.appwrite.Client
import io.appwrite.ID
import io.appwrite.models.*
import io.appwrite.services.*
object Appwrite {
lateinit var client: Client
lateinit var account: Account
fun init(context: Context) {
client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[YOUR_PROJECT_ID]")
account = Account(client)
}
suspend fun onLogin(
email: String,
password: String,
): Session {
return account.createEmailSession(
email,
password,
)
}
suspend fun onRegister(
email: String,
password: String,
): User<Map<String, Any>> {
return account.create(
userId = ID.unique(),
email,
password,
)
}
suspend fun onLogout() {
account.deleteSession("current")
}
}
``` ```
{% /section %} {% /section %}
{% section #step-5 step=5 title="Create a login page" %} {% section #step-5 step=5 title="Create a login page" %}
Add the following code to `src/App.jsx`. Add the following code to `MainActivity.kt`.
```swift ```kotlin
TODO package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.*
import androidx.compose.ui.text.input.*
import androidx.compose.ui.unit.*
import com.example.myapplication.ui.theme.MyApplicationTheme
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Appwrite.init(applicationContext)
setContent {
MyApplicationTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val coroutineScope = rememberCoroutineScope()
var user by remember { mutableStateOf("") }
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
if (user.isNotEmpty()) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(text = "Logged in as $user")
Button(onClick = {
coroutineScope.launch {
Appwrite.onLogout()
}
}) {
Text("Logout")
}
}
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
TextField(
value = email,
onValueChange = { email = it },
label = { Text("Username") },
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
TextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
Button(onClick = {
coroutineScope.launch {
try {
Appwrite.onLogin(email, password)
user = email
} catch (e: Exception) {
e.printStackTrace()
}
}
}) {
Text("Login")
}
Button(onClick = {
coroutineScope.launch {
try {
Appwrite.onRegister(email, password)
} catch (e: Exception) {
e.printStackTrace()
}
}
}) {
Text("Register")
}
}
}
}
}
}
}
}
``` ```
{% /section %} {% /section %}
{% section #step-6 step=6 title="Checkout what you've built" %} {% section #step-6 step=6 title="All set" %}
Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser. Run your project by clicking **Run app** in Android Studio.
{% /section %} {% /section %}

View File

@@ -1,9 +1,16 @@
--- ---
layout: article layout: article
title: Quick start with Angular title: Start with Angular
description: Learn how to quickly integrate Appwrite products and services into your Angular project. description: Learn how to quickly integrate Appwrite products and services into your Angular project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3
--- ---
hello world Improve the docs, add this guide.
We still don't have this guide in place, but we do have some great news.
The Appwrite docs, just like Appwrite, is completely open sourced.
This means, anyone can help improve them and add new guides and tutorials.
If you see this page, **we're actively looking for contributions to this page**.
Follow our contribution guidelines, open a PR to [our Website repo](https://github.com/appwrite/website), and collaborate with our core team to improve this page.

View File

@@ -1,61 +1,190 @@
--- ---
layout: article layout: article
title: Start with Apple title: Start with Apple
description: Learn how to quickly integrate Appwrite products and services into your iOS, iPadOS, macOS, watchOS, tvOS, or visionOS project. description: Learn how to quickly integrate Appwrite products and services into your Apple project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3
--- ---
Learn to setup your first Apple project powered by Appwrite. Learn to setup your first Apple project powered by Appwrite.
{% section #step-1 step=1 title="Create project" %}
{% section #step-1 step=1 title="Create Apple project" %}
Open Xcode and click **Create a new Xcode project**.
Choose your desired project template and click **Next**.
Now enter your app **product name** and **bundle identifier** and click **Next**. You will need both of these values later when you create your project in the Appwrite console.
Choose a directory for your project in and click **Create** to create your project.
{% /section %}
{% section #step-2 step=2 title="Create Appwrite project" %}
Head to the [Appwrite Console](https://cloud.appwrite.io/console). Head to the [Appwrite Console](https://cloud.appwrite.io/console).
![Create project screen](/images/docs/databases/quick-start/create-project.png) ![Create project screen](/images/docs/databases/quick-start/create-project.png)
If this is your first time using Appwrite, create an accout and create your first project. If this is your first time using Appwrite, create an accout and create your first project.
Then, under **Add a platform**, add a **Apple app**. The **Bundle ID** can be `example.my-app`. Then, under **Add a platform**, add an **Apple app**. Choose any of **iOS**, **macOS**, **watchOS** or **tvOS** as your Apple platform. If you are creating a multi-platform app, you can add more platforms later.
Add your app's **product name** and **bundle identifier**, your bundle identifier is the one entered when creating an Xcode project. For existing projects, you should use the **bundle identifier** from your project files **Identity** section.
![Add a platform](/images/docs/databases/quick-start/add-platform.png) ![Add a platform](/images/docs/databases/quick-start/add-platform.png)
You can skip optional steps. You can skip optional steps.
{% /section %} {% /section %}
{% section #step-2 step=2 title="Create XCode project" %}
Open XCode and select **Create a new XCode project** > select **App** > create an app named `my-app` under the **Organization Identifier** `example`. {% section #step-3 step=3 title="Add the Appwrite SDK" %}
This creates a new app with the **Bundle ID** `example.my-app`. To add the Appwrite SDK for Apple as a dependency, open the **File** menu and click **Add Packages**.
In the **Package URL** search box, enter https://github.com/appwrite/sdk-for-apple.
Once the SDK is found, select **Up to Next Major Version** as your **Dependency Rule** and click **Add Package**.
When dependency resolution is complete, click **Add Package** again to add the SDK package to your target.
In order to allow creating OAuth sessions, the following URL scheme must be added to your **Info.plist** file.
```plist
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>io.appwrite</string>
<key>CFBundleURLSchemes</key>
<array>
<string>appwrite-callback-[PROJECT_ID]</string>
</array>
</dict>
</array>
```
If you're using UIKit as opposed to SwiftUI, you will also need to add the following to your **SceneDelegate.swift** file.
```swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url,
url.absoluteString.contains("appwrite-callback") else {
return
}
WebAuthComponent.handleIncomingCookie(from: url)
}
```
{% /section %} {% /section %}
{% section #step-3 step=3 title="Install Appwrite" %} {% section #step-4 step=4 title="Create Appwrite Singleton" %}
Install the Appwrite SDK for Apple.
1. Select **File** > **Add Packages**
2. Search for the Appwrite SDK with the URL `https://github.com/appwrite/sdk-for-apple`
3. In the right panel, select your target project and add your desired version rules
4. Select Add Package and wait for package resolution to complete
5. Make sure the Appwrite package product is checked and select Add Package again
{% /section %}
{% section #step-4 step=4 title="Import Appwrite" %}
Find your project's ID in the **Settings** page. Find your project's ID in the **Settings** page.
![Settings page in Appwrite Console.](/images/docs/databases/quick-start/project-id.png) ![Settings page in Appwrite Console.](/images/docs/databases/quick-start/project-id.png)
Create a new file `src/lib/appwrite.js` and add the following code to it, replace `<YOUR_PROJECT_ID>` with your project ID. Create a new file `Appwrite.swift` and add the following code to it, replacing `[YOUR_PROJECT_ID]` with your project ID.
```swift ```swift
TODO import Foundation
import Appwrite
import JSONCodable
class Appwrite {
var client: Client
var account: Account
public init() {
self.client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[YOUR_PROJECT_ID]")
self.account = Account(client)
}
public func onRegister(
_ email: String,
_ password: String
) async throws -> User<[String: AnyCodable]> {
try await account.create(
userId: ID.unique(),
email: email,
password: password
)
}
public func onLogin(
_ email: String,
_ password: String
) async throws -> Session {
try await account.createEmailSession(
email: email,
password: password
)
}
public func onLogout() async throws {
_ = try await account.deleteSession(
sessionId: "current"
)
}
}
``` ```
{% /section %} {% /section %}
{% section #step-5 step=5 title="Create a login page" %} {% section #step-5 step=5 title="Create a login page" %}
Add the following code to `src/App.jsx`. Add the following code to `ContentView.swift`.
```swift ```swift
TODO import SwiftUI
class ViewModel: ObservableObject {
@Published var email: String = ""
@Published var password: String = ""
}
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
VStack {
TextField(
"Email",
text: $viewModel.email
)
SecureField(
"Password",
text: $viewModel.password
)
Button(
action: { Task {
try await Appwrite.onRegister(
viewModel.email,
viewModel.password
)
}},
label: {
Text("Register")
}
)
Button(
action: { Task {
try! await Appwrite.onLogin(
viewModel.email,
viewModel.password
)
}},
label: {
Text("Login")
}
)
}
.padding()
}
}
``` ```
{% /section %} {% /section %}
{% section #step-6 step=6 title="Checkout what you've built" %} {% section #step-6 step=6 title="All set" %}
Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser. Run your project by clicking **Start active scheme** in Xcode.
{% /section %} {% /section %}

View File

@@ -1,6 +1,6 @@
--- ---
layout: article layout: article
title: Quick start with Astro title: Start with Astro
description: Learn how to quickly integrate Appwrite products and services into your Astro project. description: Learn how to quickly integrate Appwrite products and services into your Astro project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3

View File

@@ -1,13 +1,22 @@
--- ---
layout: article layout: article
title: Quick start with Flutter title: Start with Flutter
description: Learn how to quickly integrate Appwrite products and services into your Flutter project. description: Learn how to quickly integrate Appwrite products and services into your Flutter project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3
--- ---
Learn to setup your first Flutter project powered by Appwrite. Learn to setup your first Flutter project powered by Appwrite.
{% section #step-1 step=1 title="Create project" %}
{% section #step-1 step=1 title="Create Flutter project" %}
Create a Flutter project.
```sh
flutter create my_app && cd my_app
```
{% /section %}
{% section #step-2 step=2 title="Create project" %}
Head to the [Appwrite Console](https://cloud.appwrite.io/console). Head to the [Appwrite Console](https://cloud.appwrite.io/console).
![Create project screen](/images/docs/databases/quick-start/create-project.png) ![Create project screen](/images/docs/databases/quick-start/create-project.png)
@@ -60,7 +69,7 @@ You have to change your iOS Deployment Target in Xcode to be iOS >= 11 to be abl
{% /tabsitem %} {% /tabsitem %}
{% tabsitem #android title="Android" %} {% tabsitem #android title="Android" %}
Add your app's **name** and *package name*, Your package name is generally the **applicationId** in your app-level [build.gradle](https://github.com/appwrite/playground-for-flutter/blob/master/android/app/build.gradle#L41) file. Add your app's **name** and **package name**, Your package name is generally the **applicationId** in your app-level [build.gradle](https://github.com/appwrite/playground-for-flutter/blob/master/android/app/build.gradle#L41) file.
In order to capture the Appwrite OAuth callback url, the following activity needs to be added inside the `<application>` tag, along side the existing `<activity>` tags in your [AndroidManifest.xml](https://github.com/appwrite/playground-for-flutter/blob/master/android/app/src/main/AndroidManifest.xml). In order to capture the Appwrite OAuth callback url, the following activity needs to be added inside the `<application>` tag, along side the existing `<activity>` tags in your [AndroidManifest.xml](https://github.com/appwrite/playground-for-flutter/blob/master/android/app/src/main/AndroidManifest.xml).
Be sure to replace the **[PROJECT_ID]** string with your actual Appwrite project ID. Be sure to replace the **[PROJECT_ID]** string with your actual Appwrite project ID.
@@ -128,17 +137,10 @@ If you cannot find the correct package name, run the application in Windows, and
{% /tabs %} {% /tabs %}
![Add a platform](/images/docs/databases/quick-start/add-platform.png) ![Add a platform]()
You can skip optional steps. You can skip optional steps.
{% /section %}
{% section #step-2 step=2 title="Create Flutter project" %}
Create a Flutter project.
```sh
flutter create my_app && cd my_app
```
{% /section %} {% /section %}
{% section #step-3 step=3 title="Install Appwrite" %} {% section #step-3 step=3 title="Install Appwrite" %}
@@ -155,60 +157,39 @@ Find your project's ID in the **Settings** page.
![Settings page in Appwrite Console.](/images/docs/databases/quick-start/project-id.png) ![Settings page in Appwrite Console.](/images/docs/databases/quick-start/project-id.png)
Create a new file `lib/appwrite.dart` and add the following code to it, replace `<YOUR_PROJECT_ID>` with your project ID. Open the generated `lib/main.dart` and add the following code to it, replace `<YOUR_PROJECT_ID>` with your project ID.
This imports and initializes Appwrite.
```dart
import 'package:appwrite/appwrite.dart';
class Appwrite {
static final Appwrite instance = Appwrite._internal();
late final Client client;
late final Account account;
factory Appwrite._() {
return instance;
}
Appwrite._internal() {
client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("<YOUR_PROJECT_ID>");
account = Account(client);
}
}
```
{% /section %}
{% section #step-5 step=5 title="Create a login page" %}
Add the following code to `src/App.jsx`.
import 'package:appwrite/appwrite.dart';
```dart ```dart
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:appwrite/appwrite.dart'; import 'package:appwrite/appwrite.dart';
import 'package:appwrite/models.dart' as models; import 'package:appwrite/models.dart' as models;
import 'package:my_app/appwrite.dart';
void main() { void main() {
runApp(MyApp()); WidgetsFlutterBinding.ensureInitialized();
} Client client = Client();
client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("650209298acac4ee1bb6");
;
Account account = Account(client);
class MyApp extends StatelessWidget { runApp(MyApp(
@override account: account,
Widget build(BuildContext context) { ));
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('My App')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: MyForm(),
),
),
);
}
} }
```
{% /section %}
{% section #step-5 step=5 title="Create a login page" %}
Then, append the following widgets to `lib/main.dart` create your login page.
import 'package:appwrite/appwrite.dart';
```dart
class MyForm extends StatefulWidget { class MyForm extends StatefulWidget {
final Account account;
MyForm({required this.account});
@override @override
MyFormState createState() { MyFormState createState() {
return MyFormState(); return MyFormState();
@@ -222,22 +203,21 @@ class MyFormState extends State<MyForm> {
final TextEditingController nameController = TextEditingController(); final TextEditingController nameController = TextEditingController();
Future<void> login(String email, String password) async { Future<void> login(String email, String password) async {
await Appwrite.instance.account await widget.account.createEmailSession(email: email, password: password);
.createEmailSession(email: email, password: password); final user = await widget.account.get();
final user = await Appwrite.instance.account.get();
setState(() { setState(() {
loggedInUser = user; loggedInUser = user;
}); });
} }
Future<void> register(String email, String password, String name) async { Future<void> register(String email, String password, String name) async {
await Appwrite.instance.account.create( await widget.account.create(
userId: ID.unique(), email: email, password: password, name: name); userId: ID.unique(), email: email, password: password, name: name);
await login(email, password); await login(email, password);
} }
Future<void> logout() async { Future<void> logout() async {
await Appwrite.instance.account.deleteSession(sessionId: 'current'); await widget.account.deleteSession(sessionId: 'current');
setState(() { setState(() {
loggedInUser = null; loggedInUser = null;
}); });
@@ -294,6 +274,6 @@ class MyFormState extends State<MyForm> {
``` ```
{% /section %} {% /section %}
{% section #step-6 step=6 title="Checkout what you've built" %} {% section #step-6 step=6 title="All set" %}
Run your project with `flutter run` and select a browser, platform, or emulator to run your project. Run your project with `flutter run` and select a browser, platform, or emulator to run your project.
{% /section %} {% /section %}

View File

@@ -1,9 +1,16 @@
--- ---
layout: article layout: article
title: Quick start with Next.js title: Start with Next.js
description: Learn how to quickly integrate Appwrite products and services into your Next.js project. description: Learn how to quickly integrate Appwrite products and services into your Next.js project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3
--- ---
hello world Improve the docs, add this guide.
We still don't have this guide in place, but we do have some great news.
The Appwrite docs, just like Appwrite, is completely open sourced.
This means, anyone can help improve them and add new guides and tutorials.
If you see this page, **we're actively looking for contributions to this page**.
Follow our contribution guidelines, open a PR to [our Website repo](https://github.com/appwrite/website), and collaborate with our core team to improve this page.

View File

@@ -1,9 +1,16 @@
--- ---
layout: article layout: article
title: Quick start with Nuxt title: Start with Nuxt
description: Learn how to quickly integrate Appwrite products and services into your Nuxt project. description: Learn how to quickly integrate Appwrite products and services into your Nuxt project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3
--- ---
hello world Improve the docs, add this guide.
We still don't have this guide in place, but we do have some great news.
The Appwrite docs, just like Appwrite, is completely open sourced.
This means, anyone can help improve them and add new guides and tutorials.
If you see this page, **we're actively looking for contributions to this page**.
Follow our contribution guidelines, open a PR to [our Website repo](https://github.com/appwrite/website), and collaborate with our core team to improve this page.

View File

@@ -1,6 +1,6 @@
--- ---
layout: article layout: article
title: Quick start with Qwik title: Start with Qwik
description: Learn how to quickly integrate Appwrite products and services into your Qwik project. description: Learn how to quickly integrate Appwrite products and services into your Qwik project.
difficulty: beginner difficulty: beginner
readtime: 3 readtime: 3

View File

@@ -117,6 +117,6 @@ export default App;
``` ```
{% /section %} {% /section %}
{% section #step-6 step=6 title="Checkout what you've built" %} {% section #step-6 step=6 title="All set" %}
Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser. Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser.
{% /section %} {% /section %}

View File

@@ -99,7 +99,7 @@ Create a new file `src/routes/index.svelte` and add the following code to it.
``` ```
{% /section %} {% /section %}
{% section #step-6 step=6 title="Checkout what you've built" %} {% section #step-6 step=6 title="All set" %}
Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser. Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser.
{% /section %} {% /section %}

View File

@@ -108,6 +108,6 @@ const logout = async () => {
``` ```
{% /section %} {% /section %}
{% section #step-6 step=6 title="Checkout what you've built" %} {% section #step-6 step=6 title="All set" %}
Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser. Run your project with `npm run dev -- --open --port 3000` and open [http://localhost:3000](http://localhost:3000) in your browser.
{% /section %} {% /section %}

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