2022-12-01 11:25:45 +00:00
|
|
|
# Svelte + Appwrite = 🚀
|
|
|
|
|
|
|
|
Blazing fast development with done backend and fully-prepared frontend.
|
|
|
|
|
2022-12-03 23:24:44 +00:00
|
|
|
CMS ready!
|
|
|
|
|
2022-12-02 16:52:06 +00:00
|
|
|
## Appwrite installation
|
|
|
|
|
|
|
|
[Appwrite installation](https://appwrite.io/docs/installation)
|
|
|
|
|
2022-12-02 16:52:43 +00:00
|
|
|
## Frontend included
|
2022-12-01 11:25:45 +00:00
|
|
|
|
|
|
|
* tailwind
|
|
|
|
* scss
|
2022-12-02 16:49:10 +00:00
|
|
|
* css reset
|
2022-12-01 11:25:45 +00:00
|
|
|
* typescript
|
|
|
|
* routing
|
2022-12-01 20:08:27 +00:00
|
|
|
* ready routes
|
2022-12-01 11:25:45 +00:00
|
|
|
* oauth
|
2022-12-08 15:09:46 +00:00
|
|
|
* files upload, download
|
2022-12-01 11:25:45 +00:00
|
|
|
* folder structure
|
|
|
|
* common components
|
|
|
|
* service worker
|
|
|
|
* path aliases
|
2022-12-01 20:08:27 +00:00
|
|
|
* database realtime subscribers
|
2022-12-08 23:43:04 +00:00
|
|
|
* database paginate, infinity scroll
|
2022-12-02 18:26:41 +00:00
|
|
|
* i18n
|
2022-12-03 23:24:44 +00:00
|
|
|
* cms
|
2022-12-04 14:58:31 +00:00
|
|
|
* cms forms components
|
2022-12-01 11:25:45 +00:00
|
|
|
* vite
|
|
|
|
* prettier
|
|
|
|
* editorconfig
|
2022-12-04 14:58:31 +00:00
|
|
|
* icons: [Bootstrap icons](https://icons.getbootstrap.com/)
|
2022-12-01 20:08:27 +00:00
|
|
|
|
|
|
|
## Database subscribers
|
|
|
|
|
2022-12-02 15:35:24 +00:00
|
|
|
```svelte
|
|
|
|
<script>
|
2022-12-08 15:09:46 +00:00
|
|
|
import { Collection } from '$lib/database'
|
2022-12-03 09:30:26 +00:00
|
|
|
import { Query } from 'appwrite'
|
2022-12-02 15:35:24 +00:00
|
|
|
|
2022-12-03 09:30:26 +00:00
|
|
|
const collection = new Collection('[database-id]', '[collection-id]')
|
2022-12-08 23:43:04 +00:00
|
|
|
const [subscriber, loading] = collection.createSubscriber([Query.limit(5) /*, ...queries */])
|
2022-12-06 21:10:53 +00:00
|
|
|
// listen changes (update, delete) in database and automatically rerender on change
|
2022-12-03 09:30:26 +00:00
|
|
|
// current data = [{ name: 'John', lastName: 'Doe' }, ...]
|
2022-12-06 21:10:53 +00:00
|
|
|
|
|
|
|
const insertSubscriber = collection.createObserver()
|
|
|
|
// listen changes (create) in database and automatically rerender on change
|
|
|
|
|
2022-12-07 12:07:13 +00:00
|
|
|
const [paginator, paginatorInitalLoading] = collection.createPaginate(10, [/* ...queries */])
|
2022-12-06 21:12:13 +00:00
|
|
|
// paginate the collection of documents with limit and automatically rerender on change
|
2022-12-07 12:07:13 +00:00
|
|
|
// paginator.next() makes the next request for items, paginator store automatically rerender on next load
|
2022-12-08 23:43:04 +00:00
|
|
|
|
|
|
|
const [scrollData, scrollDispatch] = collection.createInfinityScrollDispatcher(10, [/* ...queries */], { /* intersection observer options */ })
|
|
|
|
// load next data after scroll to anchor (scrollDispatch) element
|
2022-12-02 15:35:24 +00:00
|
|
|
</script>
|
|
|
|
|
2022-12-07 12:07:13 +00:00
|
|
|
<div>
|
2022-12-03 09:30:26 +00:00
|
|
|
{#if $loading}
|
2022-12-07 12:07:13 +00:00
|
|
|
<p>Loading data from database...</p>
|
2022-12-03 09:30:26 +00:00
|
|
|
{:else}
|
|
|
|
{#each [...$subscriber, ...$insertSubscriber] as item}
|
|
|
|
<p>{item.name}</p>
|
2022-12-02 15:35:24 +00:00
|
|
|
{/each}
|
2022-12-03 09:30:26 +00:00
|
|
|
{/if}
|
2022-12-07 12:07:13 +00:00
|
|
|
</div>
|
2022-12-08 23:43:04 +00:00
|
|
|
|
|
|
|
<!-- scroll dispatcher example -->
|
|
|
|
<div>
|
|
|
|
{#each $scrollData as item}
|
|
|
|
<p>{item.name}</p>
|
|
|
|
{/each}
|
|
|
|
<div use:scrollDispatch on:fetch={(e) => console.log(e) /* on every fetch from scroll dispatcher do some action */} />
|
|
|
|
</div>
|
2022-12-01 21:45:04 +00:00
|
|
|
```
|
|
|
|
|
2022-12-08 15:09:46 +00:00
|
|
|
## Files subscribers
|
|
|
|
|
|
|
|
```svelte
|
|
|
|
<script>
|
|
|
|
import { Bucket } from '$lib/storage'
|
|
|
|
import { Query } from 'appwrite'
|
|
|
|
|
|
|
|
const bucket = new Bucket('[bucket-id]')
|
2022-12-08 23:43:04 +00:00
|
|
|
const [files, loading] = bucket.createSubscriber([Query.limit(5) /*, ...queries */])
|
2022-12-08 15:09:46 +00:00
|
|
|
// listen changes (update, delete) in files and automatically rerender on change
|
|
|
|
|
|
|
|
const insertSubscriber = bucket.createObserver()
|
|
|
|
// listen changes (create) in files and automatically rerender on change
|
|
|
|
|
|
|
|
const [upload, dispatch] = storage.createUploadDispatcher(/* many files ? true : false, default = false */)
|
|
|
|
|
|
|
|
const [content, loading] = storage.getFileContent('6391f7c70ede82115575')
|
|
|
|
// get file content and automatically rerender on file update
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<input type="file" use:upload />
|
|
|
|
<button on:click={() => dispatch().then(uploadedFile => console.log(uploadedFile))}>Upload</button>
|
|
|
|
</div>
|
|
|
|
```
|
|
|
|
|
2022-12-01 21:45:04 +00:00
|
|
|
## Routing
|
|
|
|
|
|
|
|
```svelte
|
2022-12-03 09:30:26 +00:00
|
|
|
<script>
|
|
|
|
import { Router, Route, ProtectedRoute, Redirect, navigate, link, back, forward } from '$lib/router'
|
|
|
|
import Home from './routes/home.svelte'
|
|
|
|
import Profile from './routes/profile.svelte'
|
|
|
|
import { isLoading, user, logout } from '$lib/auth'
|
|
|
|
</script>
|
2022-12-01 21:45:04 +00:00
|
|
|
|
2022-12-03 09:30:26 +00:00
|
|
|
<main>
|
|
|
|
{#if !$isLoading}
|
2022-12-01 21:45:04 +00:00
|
|
|
<Router>
|
|
|
|
<Route path="/" component={Home}>
|
|
|
|
<ProtectedRoute path="/profile" allow={$user?.status} fallback="/" component={Profile}>
|
|
|
|
|
|
|
|
<a href="/about" use:link>About us</a>
|
|
|
|
</Router>
|
2022-12-03 09:30:26 +00:00
|
|
|
{/if}
|
|
|
|
</main>
|
2022-12-01 21:45:04 +00:00
|
|
|
```
|
|
|
|
|
2022-12-08 15:09:46 +00:00
|
|
|
### Routes structure
|
|
|
|
|
|
|
|
`__layout.svelte` the default layout for every page
|
|
|
|
|
|
|
|
`__error.svelte` the error page (404 error)
|
|
|
|
|
|
|
|
`__routes.svelte` the file includes all routes in application
|
|
|
|
|
2022-12-03 23:24:44 +00:00
|
|
|
## Social auth
|
2022-12-01 21:45:04 +00:00
|
|
|
|
|
|
|
```svelte
|
2022-12-03 09:30:26 +00:00
|
|
|
<script>
|
|
|
|
import { account, url } from '$lib/stores/appwrite'
|
|
|
|
</script>
|
|
|
|
|
2022-12-07 12:07:13 +00:00
|
|
|
<div>
|
2022-12-03 09:30:26 +00:00
|
|
|
<button on:click={() => account.createOAuth2Session('github', url.oauth.success, url.oauth.failure)}>
|
2022-12-03 23:24:44 +00:00
|
|
|
Github
|
2022-12-03 09:30:26 +00:00
|
|
|
</button>
|
2022-12-07 12:07:13 +00:00
|
|
|
</div>
|
2022-12-01 21:45:04 +00:00
|
|
|
```
|
2022-12-03 09:30:26 +00:00
|
|
|
|
|
|
|
## i18n
|
|
|
|
|
|
|
|
Locale file `src/locales/en.json`
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"page": {
|
|
|
|
"home": {
|
2022-12-06 21:10:53 +00:00
|
|
|
"title": "Appwrite svelte rocket start 🚀"
|
2022-12-03 09:30:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
```svelte
|
|
|
|
<script>
|
|
|
|
import { _, locale, locales } from 'svelte-i18n'
|
|
|
|
</script>
|
|
|
|
|
2022-12-07 12:07:13 +00:00
|
|
|
<div>
|
2022-12-03 09:30:26 +00:00
|
|
|
<h1>{$_('page.home.title')}</h1>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<p>Change language:</p>
|
|
|
|
|
|
|
|
<select bind:value={$locale}>
|
|
|
|
{#each $locales as locale}
|
|
|
|
<option value={locale}>{locale}</option>
|
|
|
|
{/each}
|
|
|
|
</select>
|
|
|
|
</div>
|
2022-12-07 12:07:13 +00:00
|
|
|
</div>
|
2022-12-03 09:30:26 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
## path aliases
|
|
|
|
|
|
|
|
`$lib` = `src/lib`
|
2022-12-03 23:24:44 +00:00
|
|
|
|
2022-12-03 09:30:26 +00:00
|
|
|
`$root` = `/`
|
2022-12-03 23:24:44 +00:00
|
|
|
|
2022-12-03 09:30:26 +00:00
|
|
|
`$src` = `src`
|
2022-12-03 23:24:44 +00:00
|
|
|
|
|
|
|
`$cms` = `cms`
|
|
|
|
|
2022-12-07 17:14:02 +00:00
|
|
|
`$routes` = `src/routes`
|
2022-12-07 12:07:13 +00:00
|
|
|
|
2022-12-03 23:24:44 +00:00
|
|
|
## commands
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run dev
|
|
|
|
```
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run build
|
|
|
|
```
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run preview
|
|
|
|
```
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run appwrite
|
|
|
|
```
|