Merge pull request #1624 from appwrite/mobile-onboarding-flows

Feat: New mobile onboarding flows
This commit is contained in:
Ernst Mulders
2025-01-28 17:56:52 +01:00
committed by GitHub
26 changed files with 1269 additions and 1188 deletions
+5 -3
View File
@@ -38,9 +38,11 @@
{disabled}
title={title ?? slotTitle?.innerText}
bind:group>
<p>
<slot />
</p>
{#if $$slots.default}
<p>
<slot />
</p>
{/if}
</Card.Selector>
</div>
<span slot="tooltip">{tooltipText}</span>
+12
View File
@@ -3,6 +3,7 @@
import { trackEvent } from '$lib/actions/analytics';
import WizardExitModal from './wizardExitModal.svelte';
import { goto } from '$app/navigation';
import { wizard } from '$lib/stores/wizard';
type $$Props =
| {
@@ -13,6 +14,7 @@
invertColumns?: boolean;
hideAside?: boolean;
hideFooter?: boolean;
onExit?: () => void;
}
| {
title: string;
@@ -22,6 +24,7 @@
invertColumns?: boolean;
hideAside?: boolean;
hideFooter?: boolean;
onExit?: () => void;
};
export let title: $$Props['title'] = '';
@@ -31,6 +34,7 @@
export let invertColumns: $$Props['invertColumns'] = false;
export let hideAside = false;
export let hideFooter = false;
export let onExit: $$Props['onExit'] = undefined;
function handleKeydown(event: KeyboardEvent) {
if (event.key === 'Escape') {
@@ -83,6 +87,14 @@
trackEvent('wizard_exit', {
from: 'prompt'
});
wizard.hide();
if (onExit) {
onExit();
// clear exit
onExit = null;
}
}}>
<slot name="exit">
Are you sure you want to exit from this process? All data will be deleted. This action
@@ -1,8 +1,7 @@
<script lang="ts">
import { Button, Step, Link, Icon, Layout } from '@appwrite.io/pink-svelte';
import { Step, Link, Icon, Layout } from '@appwrite.io/pink-svelte';
import { addPlatform } from './platforms/+page.svelte';
import { app } from '$lib/stores/app';
import { user } from '$lib/stores/user';
import { IconArrowRight } from '@appwrite.io/pink-icons-svelte';
import DatabaseImgSource from './assets/database.png';
import DatabaseImgSourceDark from './assets/database-dark.png';
@@ -21,10 +20,8 @@
import PlatformFlutterImgSource from './assets/platform-flutter.png';
import PlatformFlutterImgSourceDark from './assets/platform-flutter-dark.png';
import { base } from '$app/paths';
import { hasOnboardingDismissed, setHasOnboardingDismissed } from '$lib/helpers/onboarding';
import Wizard from './keys/wizard.svelte';
import { wizard } from '$lib/stores/wizard';
import { goto } from '$app/navigation';
import { onMount } from 'svelte';
function createKey() {
@@ -72,7 +69,7 @@
on:click={() => addPlatform(0)}>
<Layout.Stack direction="column" justifyContent="space-between">
<img
src={$app.themeInUse == 'dark'
src={$app.themeInUse === 'dark'
? PlatformWebImgSourceDark
: PlatformWebImgSource}
alt="" />
@@ -94,7 +91,7 @@
on:click={createKey}>
<Layout.Stack direction="column" justifyContent="space-between">
<img
src={$app.themeInUse == 'dark'
src={$app.themeInUse === 'dark'
? PlatformServerImgSourceDark
: PlatformServerImgSource}
alt="" />
@@ -115,7 +112,7 @@
on:click={() => addPlatform(3)}>
<Layout.Stack direction="column" justifyContent="space-between">
<img
src={$app.themeInUse == 'dark'
src={$app.themeInUse === 'dark'
? PlatformIosImgSourceDark
: PlatformIosImgSource}
alt="" />
@@ -209,7 +206,7 @@
href={`${base}/project-${projectId}/databases`}>
<Layout.Stack direction="column" justifyContent="space-between">
<img
src={$app.themeInUse == 'dark'
src={$app.themeInUse === 'dark'
? DatabaseImgSourceDark
: DatabaseImgSource}
alt="" />
@@ -280,7 +277,7 @@
</Layout.Stack>
</div>
<img
src={$app.themeInUse == 'dark'
src={$app.themeInUse === 'dark'
? UsersImgSourceDark
: UsersImgSource}
alt="" />
@@ -289,7 +286,7 @@
<div class="card-content">
<Layout.Stack direction="column" justifyContent="space-between">
<img
src={$app.themeInUse == 'dark'
src={$app.themeInUse === 'dark'
? DiscordImgSourceDark
: DiscordImgSource}
class="discord"
@@ -5,7 +5,6 @@
import CreateAndroid from './createAndroid.svelte';
import CreateApple from './createApple.svelte';
import CreateFlutter from './createFlutter.svelte';
import CreateWeb from './createWeb.svelte';
import CreateReactNative from './createReactNative.svelte';
import { versions } from './wizard/store';
@@ -23,7 +22,6 @@
}
const platforms = {
[Platform.Web]: CreateWeb,
[Platform.Flutter]: CreateFlutter,
[Platform.Android]: CreateAndroid,
[Platform.Apple]: CreateApple,
@@ -56,7 +54,6 @@
'flutter-macos' = 'macOS',
'flutter-windows' = 'Windows',
'flutter-web' = 'Web',
'web' = 'Web',
'react-native-android' = 'Android',
'react-native-ios' = 'iOS'
}
@@ -73,8 +70,6 @@
return 'color/apple';
} else if (platform.includes('android')) {
return 'color/android';
} else if (platform.includes('web')) {
return 'grayscale/code';
} else {
return 'unknown';
}
@@ -95,7 +90,6 @@
</Button>
{/if}
<svelte:fragment slot="list">
<DropListItem on:click={() => addPlatform(Platform.Web)}>Web app</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Flutter)}>Flutter app</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Android)}>Android app</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Apple)}>Apple app</DropListItem>
@@ -169,9 +163,6 @@
</Button>
{/if}
<svelte:fragment slot="list">
<DropListItem on:click={() => addPlatform(Platform.Web)}>
Web
</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Flutter)}>
Flutter
</DropListItem>
@@ -181,6 +172,9 @@
<DropListItem on:click={() => addPlatform(Platform.Apple)}>
Apple
</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.ReactNative)}>
React Native
</DropListItem>
</svelte:fragment>
</DropList>
</div>
@@ -0,0 +1,79 @@
<script lang="ts">
import { Icon } from '@appwrite.io/pink-svelte';
import { IconCheck } from '@appwrite.io/pink-icons-svelte';
export let status: boolean = false;
</script>
<div class="connection-line u-flex u-cross-center">
<div
class="line-left"
style={`opacity: ${status ? 1 : 0.15}; transition: opacity 5s;`}
data-status={status}>
</div>
<div
class="tick-container"
style={`opacity: ${status ? 1 : 0.15}; transition: opacity 2.5s;`}
data-status={status}>
{#if status}
<!-- todo: xs missing atm, need to test -->
<Icon icon={IconCheck} size="s" color="#fd366e" />
{/if}
</div>
<div
class="line-right"
style={`opacity: ${status ? 1 : 0.15}; transition: opacity 5s;`}
data-status={status}>
</div>
</div>
<style>
.connection-line {
display: flex;
width: 6.125rem;
align-items: center;
}
.line-left[data-status='false'],
.line-right[data-status='false'] {
flex: 1;
height: 1px;
background: none;
border-top: 1px dashed #d8d8db;
}
.line-left[data-status='true'] {
flex: 1;
height: 1px;
background: linear-gradient(to left, #f02e65 0%, rgba(254, 149, 103, 0.15) 100%);
}
.line-right[data-status='true'] {
flex: 1;
height: 1px;
background: linear-gradient(to right, #f02e65 6.32%, rgba(254, 149, 103, 0.15) 116.81%);
}
.tick-container[data-status='false'] {
width: 7px;
height: 7px;
display: flex;
border-radius: 50%;
margin-inline: 0.25rem;
background-color: #ccc;
}
.tick-container[data-status='true'] {
display: flex;
width: 25px;
height: 25px;
color: #fd366e;
border-radius: 50%;
align-items: center;
justify-content: center;
border: 1.8px solid hsla(343, 98%, 60%, 0.32);
background-color: hsla(343, 98%, 60%, 0.08);
}
</style>
@@ -0,0 +1,63 @@
<script lang="ts">
import type { ComponentType } from 'svelte';
export let icon: ComponentType;
export let iconSize: number | undefined = undefined;
export let iconColor: string | undefined = undefined;
</script>
<div class="outer-card">
<div
class="inner-card"
style="
--icon-color: {iconColor || 'inherit'};
--icon-size: {iconSize ? `${iconSize}rem` : 'inherit'};
">
<svelte:component this={icon} />
</div>
</div>
<style lang="scss">
.outer-card {
display: flex;
align-items: center;
justify-content: center;
width: 94.304px;
height: 94.303px;
flex-shrink: 0;
border-radius: 26.944px;
border: 1.684px solid rgba(255, 255, 255, 0.08);
background: rgba(255, 255, 255, 0.5);
box-shadow: 0 8.757px 8.757px 0 rgba(0, 0, 0, 0.04);
}
.inner-card {
display: flex;
align-items: center;
justify-content: center;
width: 80.832px;
height: 80.831px;
flex-shrink: 0;
border-radius: 20.208px;
background: #fff;
border: 0.54px solid #ededf0;
box-shadow: 0 6.736px 6.736px 0 rgba(0, 0, 0, 0.05);
& :global(svg) {
width: var(--icon-size);
height: var(--icon-size);
color: var(--icon-color);
}
}
:global(.theme-dark) {
& .outer-card {
background: rgba(255, 255, 255, 0.08);
}
& .inner-card {
border: 0.54px solid rgba(237, 237, 240, 0.08);
background: var(--color-bgColor-neutral-primary, #1d1d21);
}
}
</style>
@@ -1,46 +1,247 @@
<script lang="ts">
import { WizardWithSteps } from '$lib/layout';
import { Wizard } from '$lib/layout';
import { invalidate } from '$app/navigation';
import { wizard } from '$lib/stores/wizard';
import { createPlatform } from './wizard/store';
import { Dependencies } from '$lib/constants';
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
import Step1 from './wizard/android/step1.svelte';
import Step2 from './wizard/android/step2.svelte';
import Step3 from './wizard/android/step3.svelte';
import Step4 from './wizard/step4.svelte';
import {
Code,
Layout,
Icon,
Typography,
Fieldset,
InlineCode,
Spinner
} from '@appwrite.io/pink-svelte';
import { Button, Form, InputText } from '$lib/elements/forms';
import { IconAndroid, IconAppwrite } from '@appwrite.io/pink-icons-svelte';
import { Card } from '$lib/components';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { onMount } from 'svelte';
import { sdk } from '$lib/stores/sdk';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { addNotification } from '$lib/stores/notifications';
import { fade } from 'svelte/transition';
import ConnectionLine from './components/ConnectionLine.svelte';
import OnboardingPlatformCard from './components/OnboardingPlatformCard.svelte';
import { PlatformType } from '@appwrite.io/console';
import { isCloud } from '$lib/system';
async function onFinish() {
await Promise.all([invalidate(Dependencies.PROJECT), invalidate(Dependencies.PLATFORMS)]);
createPlatform.reset();
wizard.hide();
let showExitModal = false;
let isPlatformCreated = false;
let isCreatingPlatform = false;
let connectionSuccessful = false;
const projectId = $page.params.project;
const gitCloneCode =
'\ngit clone https://github.com/appwrite/starter-for-android\ncd starter-for-android\n';
const updateConfigCode = isCloud
? `const val APPWRITE_PROJECT_ID = "${projectId}"`
: `const val APPWRITE_PROJECT_ID = "${projectId}"
const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject.client.config.endpoint}"
`;
async function createAndroidPlatform() {
try {
isCreatingPlatform = true;
await sdk.forConsole.projects.createPlatform(
projectId,
PlatformType.Android,
$createPlatform.name,
$createPlatform.key || undefined,
undefined,
undefined
);
isPlatformCreated = true;
trackEvent(Submit.PlatformCreate, {
type: 'android'
});
await Promise.all([
invalidate(Dependencies.PROJECT),
invalidate(Dependencies.PLATFORMS)
]);
} catch (error) {
trackError(error, Submit.PlatformCreate);
addNotification({
type: 'error',
message: error.message
});
} finally {
isCreatingPlatform = false;
}
}
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Settings',
component: Step1
});
stepsComponents.set(2, {
label: 'Install',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: 'Import',
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'Build',
component: Step4,
optional: true
async function resetPlatformStore() {
createPlatform.reset();
}
onMount(() => {
const unsubscribe = sdk.forConsole.client.subscribe('console', (response) => {
if (response.events.includes(`projects.${projectId}.ping`) && isPlatformCreated) {
connectionSuccessful = true;
unsubscribe();
}
});
return () => {
unsubscribe();
resetPlatformStore();
};
});
</script>
<WizardWithSteps
title="Add an Android platform"
steps={stepsComponents}
on:finish={onFinish}
on:exit={onFinish}
finalAction="Go to dashboard" />
<Wizard title="Add Android platform" bind:showExitModal confirmExit>
<Form onSubmit={createAndroidPlatform}>
<Layout.Stack gap="xxl">
<!-- Step One -->
{#if !isPlatformCreated}
<Fieldset legend="Details">
<Layout.Stack gap="l" alignItems="flex-end">
<Layout.Stack gap="s">
<InputText
id="name"
label="Name"
placeholder="My Android App"
required
bind:value={$createPlatform.name} />
<!-- Tooltips on InputText don't work as of now -->
<InputText
id="key"
label="Package name"
placeholder="com.company.appname"
tooltip="Your package name is generally the applicationId in your app-level build.gradle file."
required
bind:value={$createPlatform.key} />
</Layout.Stack>
<Button
fullWidthMobile
size="s"
submit
forceShowLoader
submissionLoader={isCreatingPlatform}
disabled={!$createPlatform.name ||
!$createPlatform.key ||
isCreatingPlatform}>
Create platform
</Button>
</Layout.Stack>
</Fieldset>
{:else}
<Layout.Stack gap="xxl">
<Card isTile padding="s" radius="s">
<Layout.Stack
direction="row"
justifyContent="space-between"
alignItems="center"
gap="xs">
<Layout.Stack direction="row" alignItems="center" gap="s">
<Icon size="m" icon={IconAndroid} />
<Typography.Text
variant="m-400"
color="--color-fgcolor-neutral-primary">
{$createPlatform.name} ({$createPlatform.key})
</Typography.Text>
</Layout.Stack>
</Layout.Stack>
</Card>
</Layout.Stack>
{/if}
<!-- Step Two -->
{#if isPlatformCreated}
<Fieldset legend="Clone starter">
<Layout.Stack gap="l">
<Typography.Text variant="m-500">
1. Clone the starter kit from GitHub using the terminal or Android
Studio.
</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="bash" lineNumbers code={gitCloneCode} />
</div>
<Typography.Text variant="m-500"
>2. Open the file <InlineCode
size="s"
code="data/repository/AppwriteRepository.kt" /> and update the configuration
settings.</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="kotlin" lineNumbers code={updateConfigCode} />
</div>
<Typography.Text variant="m-500"
>3. Run the app on a connected device or emulator, then click the <InlineCode
size="s"
code="Send a ping" /> button to verify the setup.</Typography.Text>
</Layout.Stack>
</Fieldset>
{/if}
</Layout.Stack>
</Form>
<svelte:fragment slot="aside">
<Card padding="l" class="responsive-padding">
<Layout.Stack gap="xxl">
<Layout.Stack direction="row" justifyContent="center" gap="none">
<OnboardingPlatformCard
iconSize={2.526}
iconColor="#3ddc84"
icon={IconAndroid} />
<ConnectionLine status={connectionSuccessful} />
<OnboardingPlatformCard
iconSize={2.526}
iconColor="#FD366E"
icon={IconAppwrite} />
</Layout.Stack>
<Layout.Stack direction="row" justifyContent="center" alignItems="center" gap="l">
{#if !connectionSuccessful}
<Spinner />
<Typography.Text variant="m-400">Waiting for connection...</Typography.Text>
{:else}
<!-- cannot apply fade on components -->
<div
in:fade={{ duration: 2500 }}
class="u-flex u-flex-vertical u-cross-center u-gap-8">
<Typography.Title size="m">Congratulations!</Typography.Title>
<Typography.Text variant="m-400"
>You connected your app successfully.</Typography.Text>
</div>
{/if}
</Layout.Stack>
</Layout.Stack>
</Card>
</svelte:fragment>
<svelte:fragment slot="footer">
<Button
size="s"
fullWidthMobile
secondary
disabled={isCreatingPlatform}
href={`${base}/project-${projectId}/overview`}>
Go to dashboard
</Button>
</svelte:fragment>
</Wizard>
<style lang="scss">
:global(.pink2-code-margin-fix pre) {
margin: revert;
}
:global(.responsive-padding) {
@media (max-width: 768px) {
padding: 16px;
}
}
</style>
@@ -1,47 +1,271 @@
<script lang="ts">
import { WizardWithSteps } from '$lib/layout';
import { Wizard } from '$lib/layout';
import { invalidate } from '$app/navigation';
import { wizard } from '$lib/stores/wizard';
import { createPlatform } from './wizard/store';
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
import Step1 from './wizard/apple/step1.svelte';
import Step2 from './wizard/apple/step2.svelte';
import Step3 from './wizard/apple/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { Dependencies } from '$lib/constants';
import {
Code,
Layout,
Icon,
Typography,
Fieldset,
InlineCode,
Spinner
} from '@appwrite.io/pink-svelte';
import { Button, Form, InputText } from '$lib/elements/forms';
import { IconApple, IconAppwrite } from '@appwrite.io/pink-icons-svelte';
import { Card } from '$lib/components';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { onMount } from 'svelte';
import { sdk } from '$lib/stores/sdk';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { addNotification } from '$lib/stores/notifications';
import { fade } from 'svelte/transition';
import ConnectionLine from './components/ConnectionLine.svelte';
import OnboardingPlatformCard from './components/OnboardingPlatformCard.svelte';
import { PlatformType } from '@appwrite.io/console';
import { isCloud } from '$lib/system';
import { app } from '$lib/stores/app';
import { LabelCard } from '$lib/components';
async function onFinish() {
await Promise.all([invalidate(Dependencies.PROJECT), invalidate(Dependencies.PLATFORMS)]);
let showExitModal = false;
let isPlatformCreated = false;
let isCreatingPlatform = false;
let connectionSuccessful = false;
const projectId = $page.params.project;
createPlatform.reset();
wizard.hide();
const gitCloneCode =
'\ngit clone https://github.com/appwrite/starter-for-ios\ncd starter-for-ios\n';
const updateConfigCode = isCloud
? `APPWRITE_PROJECT_ID: "${projectId}"`
: `APPWRITE_PROJECT_ID: "${projectId}"
APPWRITE_PUBLIC_ENDPOINT: "${sdk.forProject.client.config.endpoint}"
`;
let platform: PlatformType = PlatformType.Appleios;
let platforms: { [key: string]: PlatformType } = {
iOS: PlatformType.Appleios,
macOS: PlatformType.Applemacos,
watchOS: PlatformType.Applewatchos,
tvOS: PlatformType.Appletvos
};
async function createApplePlatform() {
try {
isCreatingPlatform = true;
await sdk.forConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
$createPlatform.key || undefined,
undefined,
undefined
);
isPlatformCreated = true;
trackEvent(Submit.PlatformCreate, {
type: platform
});
await Promise.all([
invalidate(Dependencies.PROJECT),
invalidate(Dependencies.PLATFORMS)
]);
} catch (error) {
trackError(error, Submit.PlatformCreate);
addNotification({
type: 'error',
message: error.message
});
} finally {
isCreatingPlatform = false;
}
}
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Settings',
component: Step1
});
stepsComponents.set(2, {
label: 'Install',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: 'Import',
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'Build',
component: Step4,
optional: true
async function resetPlatformStore() {
createPlatform.reset();
}
onMount(() => {
const unsubscribe = sdk.forConsole.client.subscribe('console', (response) => {
if (response.events.includes(`projects.${projectId}.ping`) && isPlatformCreated) {
connectionSuccessful = true;
unsubscribe();
}
});
return () => {
unsubscribe();
resetPlatformStore();
};
});
</script>
<WizardWithSteps
title="Add an Apple platform"
steps={stepsComponents}
on:finish={onFinish}
on:exit={onFinish}
finalAction="Go to dashboard" />
<Wizard title="Add Apple platform" bind:showExitModal confirmExit>
<Form onSubmit={createApplePlatform}>
<Layout.Stack gap="xxl">
<!-- Step One -->
<Layout.Stack gap="l" direction="row">
{#each Object.entries(platforms) as [key, value]}
<div class="u-width-full-line">
<!-- TODO: https://github.com/appwrite/pink/pull/248 for correct spacing -->
<LabelCard
name={key}
bind:group={platform}
variant="primary"
{value}
title={key} />
</div>
{/each}
</Layout.Stack>
<!-- Step Two -->
{#if !isPlatformCreated}
<Fieldset legend="Details">
<Layout.Stack gap="l" alignItems="flex-end">
<Layout.Stack gap="s">
<InputText
id="name"
label="Name"
placeholder="My Apple App"
required
bind:value={$createPlatform.name} />
<!-- Tooltips on InputText don't work as of now -->
<InputText
id="hostname"
label="Bundle ID"
placeholder="com.company.appname"
tooltip="You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
required
bind:value={$createPlatform.key} />
</Layout.Stack>
<Button
fullWidthMobile
size="s"
submit
forceShowLoader
submissionLoader={isCreatingPlatform}
disabled={!platform ||
!$createPlatform.name ||
!$createPlatform.key ||
isCreatingPlatform}>
Create platform
</Button>
</Layout.Stack>
</Fieldset>
{:else}
<Layout.Stack gap="xxl">
<Card isTile padding="s" radius="s">
<Layout.Stack
direction="row"
justifyContent="space-between"
alignItems="center"
gap="xs">
<Layout.Stack direction="row" alignItems="center" gap="s">
<Icon size="m" icon={IconApple} />
<Typography.Text
variant="m-400"
color="--color-fgcolor-neutral-primary">
{$createPlatform.name} ({$createPlatform.key})
</Typography.Text>
</Layout.Stack>
</Layout.Stack>
</Card>
</Layout.Stack>
{/if}
<!-- Step Three -->
{#if isPlatformCreated}
<Fieldset legend="Clone starter">
<Layout.Stack gap="l">
<Typography.Text variant="m-500">
1. Clone the starter kit from GitHub using the terminal or XCode.
</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="bash" lineNumbers code={gitCloneCode} />
</div>
<Typography.Text variant="m-500"
>2. Open the file <InlineCode size="s" code="Sources/Config.plist" /> and
update the configuration settings.</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="plaintext" lineNumbers code={updateConfigCode} />
</div>
<Typography.Text variant="m-500"
>3. Run the app on a connected device or simulator, then click the <InlineCode
size="s"
code="Send a ping" /> button to verify the setup.</Typography.Text>
</Layout.Stack>
</Fieldset>
{/if}
</Layout.Stack>
</Form>
<svelte:fragment slot="aside">
<Card padding="l" class="responsive-padding">
<Layout.Stack gap="xxl">
<Layout.Stack direction="row" justifyContent="center" gap="none">
<OnboardingPlatformCard
iconSize={2.526}
iconColor={$app.themeInUse === 'light' ? '#000' : '#fff'}
icon={IconApple} />
<ConnectionLine status={connectionSuccessful} />
<OnboardingPlatformCard
iconSize={2.526}
iconColor="#FD366E"
icon={IconAppwrite} />
</Layout.Stack>
<Layout.Stack direction="row" justifyContent="center" alignItems="center" gap="l">
{#if !connectionSuccessful}
<Spinner />
<Typography.Text variant="m-400">Waiting for connection...</Typography.Text>
{:else}
<!-- cannot apply fade on components -->
<div
in:fade={{ duration: 2500 }}
class="u-flex u-flex-vertical u-cross-center u-gap-8">
<Typography.Title size="m">Congratulations!</Typography.Title>
<Typography.Text variant="m-400"
>You connected your app successfully.</Typography.Text>
</div>
{/if}
</Layout.Stack>
</Layout.Stack>
</Card>
</svelte:fragment>
<svelte:fragment slot="footer">
<Button
size="s"
fullWidthMobile
secondary
disabled={isCreatingPlatform}
href={`${base}/project-${projectId}/overview`}>
Go to dashboard
</Button>
</svelte:fragment>
</Wizard>
<style lang="scss">
:global(.pink2-code-margin-fix pre) {
margin: revert;
}
:global(.responsive-padding) {
@media (max-width: 768px) {
padding: 16px;
}
}
</style>
@@ -1,47 +1,329 @@
<script lang="ts">
import { WizardWithSteps } from '$lib/layout';
import { Wizard } from '$lib/layout';
import { invalidate } from '$app/navigation';
import { wizard } from '$lib/stores/wizard';
import { createPlatform } from './wizard/store';
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
import Step1 from './wizard/flutter/step1.svelte';
import Step2 from './wizard/flutter/step2.svelte';
import Step3 from './wizard/flutter/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { Dependencies } from '$lib/constants';
import {
Code,
Layout,
Icon,
Typography,
Fieldset,
InlineCode,
Spinner
} from '@appwrite.io/pink-svelte';
import { Button, Form, InputText } from '$lib/elements/forms';
import { IconFlutter, IconAppwrite } from '@appwrite.io/pink-icons-svelte';
import { Card } from '$lib/components';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { onMount } from 'svelte';
import { sdk } from '$lib/stores/sdk';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { addNotification } from '$lib/stores/notifications';
import { fade } from 'svelte/transition';
import ConnectionLine from './components/ConnectionLine.svelte';
import OnboardingPlatformCard from './components/OnboardingPlatformCard.svelte';
import { PlatformType } from '@appwrite.io/console';
import { isCloud } from '$lib/system';
import { LabelCard } from '$lib/components';
async function onFinish() {
await Promise.all([invalidate(Dependencies.PROJECT), invalidate(Dependencies.PLATFORMS)]);
let showExitModal = false;
let isPlatformCreated = false;
let isCreatingPlatform = false;
let connectionSuccessful = false;
const projectId = $page.params.project;
createPlatform.reset();
wizard.hide();
const gitCloneCode =
'\ngit clone https://github.com/appwrite/starter-for-flutter\ncd starter-for-flutter\n';
const updateConfigCode = isCloud
? `static const String APPWRITE_PROJECT_ID = "${projectId}"`
: `static const String APPWRITE_PROJECT_ID = "${projectId}"
static const String APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject.client.config.endpoint}"
`;
let platform: PlatformType = PlatformType.Flutterandroid;
let platforms: { [key: string]: PlatformType } = {
Android: PlatformType.Flutterandroid,
iOS: PlatformType.Flutterios,
Linux: PlatformType.Flutterlinux,
macOS: PlatformType.Fluttermacos,
Windows: PlatformType.Flutterwindows,
Web: PlatformType.Flutterweb
};
const placeholder: Partial<
Record<
PlatformType,
{
name: string;
hostname: string;
tooltip: string;
}
>
> = {
[PlatformType.Flutterandroid]: {
name: 'My Android App',
hostname: 'com.company.appname',
tooltip:
'Your package name is generally the applicationId in your app-level build.gradle file.'
},
[PlatformType.Flutterios]: {
name: 'My iOS App',
hostname: 'com.company.appname',
tooltip:
"You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
},
[PlatformType.Flutterlinux]: {
name: 'My Linux App',
hostname: 'appname',
tooltip: 'Your application name'
},
[PlatformType.Fluttermacos]: {
name: 'My mac OS App',
hostname: 'com.company.appname',
tooltip:
"You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
},
[PlatformType.Flutterwindows]: {
name: 'My Windows App',
hostname: 'appname',
tooltip: 'Your application name'
},
[PlatformType.Flutterweb]: {
name: 'My Web App',
hostname: 'localhost',
tooltip:
'The hostname that your website will use to interact with the Appwrite APIs in production or development environments. No protocol or port number required.'
}
};
const hostname: Partial<Record<PlatformType, string>> = {
[PlatformType.Flutterandroid]: 'Package Name',
[PlatformType.Flutterios]: 'Bundle ID',
[PlatformType.Flutterlinux]: 'Package Name',
[PlatformType.Fluttermacos]: 'Bundle ID',
[PlatformType.Flutterweb]: 'Hostname',
[PlatformType.Flutterwindows]: 'Package Name'
};
async function createFlutterPlatform() {
try {
isCreatingPlatform = true;
await sdk.forConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
$createPlatform.key || undefined,
undefined,
undefined
);
isPlatformCreated = true;
trackEvent(Submit.PlatformCreate, {
type: platform
});
await Promise.all([
invalidate(Dependencies.PROJECT),
invalidate(Dependencies.PLATFORMS)
]);
} catch (error) {
trackError(error, Submit.PlatformCreate);
addNotification({
type: 'error',
message: error.message
});
} finally {
isCreatingPlatform = false;
}
}
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Settings',
component: Step1
});
stepsComponents.set(2, {
label: 'Install',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: 'Import',
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'Build',
component: Step4,
optional: true
async function resetPlatformStore() {
createPlatform.reset();
}
onMount(() => {
const unsubscribe = sdk.forConsole.client.subscribe('console', (response) => {
if (response.events.includes(`projects.${projectId}.ping`) && isPlatformCreated) {
connectionSuccessful = true;
unsubscribe();
}
});
return () => {
unsubscribe();
resetPlatformStore();
};
});
</script>
<WizardWithSteps
title="Add a Flutter platform"
steps={stepsComponents}
on:finish={onFinish}
on:exit={onFinish}
finalAction="Go to dashboard" />
<Wizard title="Add Flutter platform" bind:showExitModal confirmExit>
<Form onSubmit={createFlutterPlatform}>
<Layout.Stack gap="xxl">
<!-- Step One -->
<Layout.Stack gap="l" direction="row">
{#each Object.entries(platforms) as [key, value]}
<div class="u-width-full-line">
<!-- TODO: https://github.com/appwrite/pink/pull/248 for correct spacing -->
<LabelCard
name={key}
bind:group={platform}
variant="primary"
{value}
title={key} />
</div>
{/each}
</Layout.Stack>
<!-- Step Two -->
{#if !isPlatformCreated}
<Fieldset legend="Details">
<Layout.Stack gap="l" alignItems="flex-end">
<Layout.Stack gap="s">
<InputText
id="name"
label="Name"
placeholder={placeholder[platform].name}
required
bind:value={$createPlatform.name} />
<!-- Tooltips on InputText don't work as of now -->
<InputText
id="hostname"
label={hostname[platform]}
placeholder={placeholder[platform].hostname}
tooltip={placeholder[platform].tooltip}
required
bind:value={$createPlatform.key} />
</Layout.Stack>
<Button
fullWidthMobile
size="s"
submit
forceShowLoader
submissionLoader={isCreatingPlatform}
disabled={!platform ||
!$createPlatform.name ||
!$createPlatform.key ||
isCreatingPlatform}>
Create platform
</Button>
</Layout.Stack>
</Fieldset>
{:else}
<Layout.Stack gap="xxl">
<Card isTile padding="s" radius="s">
<Layout.Stack
direction="row"
justifyContent="space-between"
alignItems="center"
gap="xs">
<Layout.Stack direction="row" alignItems="center" gap="s">
<Icon size="m" icon={IconFlutter} />
<Typography.Text
variant="m-400"
color="--color-fgcolor-neutral-primary">
{$createPlatform.name} ({$createPlatform.key})
</Typography.Text>
</Layout.Stack>
</Layout.Stack>
</Card>
</Layout.Stack>
{/if}
<!-- Step Three -->
{#if isPlatformCreated}
<Fieldset legend="Clone starter">
<Layout.Stack gap="l">
<Typography.Text variant="m-500">
1. Clone the starter kit from GitHub using the terminal, Android Studio
or VSCode.
</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="bash" lineNumbers code={gitCloneCode} />
</div>
<Typography.Text variant="m-500"
>2. Open the file <InlineCode
size="s"
code="lib/constants/appwrite.dart" /> and update the configuration settings.</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="dart" lineNumbers code={updateConfigCode} />
</div>
<Typography.Text variant="m-500"
>3. Run the app on a connected device or simulator, then click the <InlineCode
size="s"
code="Send a ping" /> button to verify the setup.</Typography.Text>
</Layout.Stack>
</Fieldset>
{/if}
</Layout.Stack>
</Form>
<svelte:fragment slot="aside">
<Card padding="l" class="responsive-padding">
<Layout.Stack gap="xxl">
<Layout.Stack direction="row" justifyContent="center" gap="none">
<OnboardingPlatformCard
iconSize={2.526}
iconColor="#47C5FB"
icon={IconFlutter} />
<ConnectionLine status={connectionSuccessful} />
<OnboardingPlatformCard
iconSize={2.526}
iconColor="#FD366E"
icon={IconAppwrite} />
</Layout.Stack>
<Layout.Stack direction="row" justifyContent="center" alignItems="center" gap="l">
{#if !connectionSuccessful}
<Spinner />
<Typography.Text variant="m-400">Waiting for connection...</Typography.Text>
{:else}
<!-- cannot apply fade on components -->
<div
in:fade={{ duration: 2500 }}
class="u-flex u-flex-vertical u-cross-center u-gap-8">
<Typography.Title size="m">Congratulations!</Typography.Title>
<Typography.Text variant="m-400"
>You connected your app successfully.</Typography.Text>
</div>
{/if}
</Layout.Stack>
</Layout.Stack>
</Card>
</svelte:fragment>
<svelte:fragment slot="footer">
<Button
size="s"
fullWidthMobile
secondary
disabled={isCreatingPlatform}
href={`${base}/project-${projectId}/overview`}>
Go to dashboard
</Button>
</svelte:fragment>
</Wizard>
<style lang="scss">
:global(.pink2-code-margin-fix pre) {
margin: revert;
}
:global(.responsive-padding) {
@media (max-width: 768px) {
padding: 16px;
}
}
</style>
@@ -1,47 +1,296 @@
<script lang="ts">
import { WizardWithSteps } from '$lib/layout';
import { Wizard } from '$lib/layout';
import { invalidate } from '$app/navigation';
import { wizard } from '$lib/stores/wizard';
import { createPlatform } from './wizard/store';
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
import Step1 from './wizard/react-native/step1.svelte';
import Step2 from './wizard/react-native/step2.svelte';
import Step3 from './wizard/react-native/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { Dependencies } from '$lib/constants';
import {
Code,
Layout,
Icon,
Typography,
Fieldset,
InlineCode,
Spinner
} from '@appwrite.io/pink-svelte';
import { Button, Form, InputText } from '$lib/elements/forms';
import { IconReact, IconAppwrite } from '@appwrite.io/pink-icons-svelte';
import { Card } from '$lib/components';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { onMount } from 'svelte';
import { sdk } from '$lib/stores/sdk';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { addNotification } from '$lib/stores/notifications';
import { fade } from 'svelte/transition';
import ConnectionLine from './components/ConnectionLine.svelte';
import OnboardingPlatformCard from './components/OnboardingPlatformCard.svelte';
import { PlatformType } from '@appwrite.io/console';
import { isCloud } from '$lib/system';
import { LabelCard } from '$lib/components';
async function onFinish() {
await Promise.all([invalidate(Dependencies.PROJECT), invalidate(Dependencies.PLATFORMS)]);
let showExitModal = false;
let isPlatformCreated = false;
let isCreatingPlatform = false;
let connectionSuccessful = false;
const projectId = $page.params.project;
createPlatform.reset();
wizard.hide();
const gitCloneCode =
'\ngit clone https://github.com/appwrite/starter-for-react-native\ncd starter-for-react-native\n';
const updateConfigCode = isCloud
? `const APPWRITE_PROJECT_ID = "${projectId}";`
: `const APPWRITE_PROJECT_ID = "${projectId}";
const APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject.client.config.endpoint}";
`;
let platform: PlatformType = PlatformType.Reactnativeandroid;
let platforms: { [key: string]: PlatformType } = {
Android: PlatformType.Reactnativeandroid,
iOS: PlatformType.Reactnativeios
};
const placeholder: Partial<
Record<
PlatformType,
{
name: string;
hostname: string;
tooltip: string;
}
>
> = {
[PlatformType.Reactnativeandroid]: {
name: 'My Android App',
hostname: 'com.company.appname',
tooltip:
'Your package name is generally the applicationId in your app-level build.gradle file.'
},
[PlatformType.Reactnativeios]: {
name: 'My iOS App',
hostname: 'com.company.appname',
tooltip:
"You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
}
};
const hostname: Partial<Record<PlatformType, string>> = {
[PlatformType.Reactnativeandroid]: 'Package Name',
[PlatformType.Reactnativeios]: 'Bundle ID'
};
async function createFlutterPlatform() {
try {
isCreatingPlatform = true;
await sdk.forConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
$createPlatform.key || undefined,
undefined,
undefined
);
isPlatformCreated = true;
trackEvent(Submit.PlatformCreate, {
type: platform
});
await Promise.all([
invalidate(Dependencies.PROJECT),
invalidate(Dependencies.PLATFORMS)
]);
} catch (error) {
trackError(error, Submit.PlatformCreate);
addNotification({
type: 'error',
message: error.message
});
} finally {
isCreatingPlatform = false;
}
}
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Settings',
component: Step1
});
stepsComponents.set(2, {
label: 'Install',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: 'Import',
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'Build',
component: Step4,
optional: true
async function resetPlatformStore() {
createPlatform.reset();
}
onMount(() => {
const unsubscribe = sdk.forConsole.client.subscribe('console', (response) => {
if (response.events.includes(`projects.${projectId}.ping`) && isPlatformCreated) {
connectionSuccessful = true;
unsubscribe();
}
});
return () => {
unsubscribe();
resetPlatformStore();
};
});
</script>
<WizardWithSteps
title="Add a React Native platform"
steps={stepsComponents}
on:finish={onFinish}
on:exit={onFinish}
finalAction="Go to dashboard" />
<Wizard title="Add React Native platform" bind:showExitModal confirmExit>
<Form onSubmit={createFlutterPlatform}>
<Layout.Stack gap="xxl">
<!-- Step One -->
<Layout.Stack gap="l" direction="row">
{#each Object.entries(platforms) as [key, value]}
<div class="u-width-full-line">
<!-- TODO: https://github.com/appwrite/pink/pull/248 for correct spacing -->
<LabelCard
name={key}
bind:group={platform}
variant="primary"
{value}
title={key} />
</div>
{/each}
</Layout.Stack>
<!-- Step Two -->
{#if !isPlatformCreated}
<Fieldset legend="Details">
<Layout.Stack gap="l" alignItems="flex-end">
<Layout.Stack gap="s">
<InputText
id="name"
label="Name"
placeholder={placeholder[platform].name}
required
bind:value={$createPlatform.name} />
<!-- Tooltips on InputText don't work as of now -->
<InputText
id="hostname"
label={hostname[platform]}
placeholder={placeholder[platform].hostname}
tooltip={placeholder[platform].tooltip}
required
bind:value={$createPlatform.key} />
</Layout.Stack>
<Button
fullWidthMobile
size="s"
submit
forceShowLoader
submissionLoader={isCreatingPlatform}
disabled={!platform ||
!$createPlatform.name ||
!$createPlatform.key ||
isCreatingPlatform}>
Create platform
</Button>
</Layout.Stack>
</Fieldset>
{:else}
<Layout.Stack gap="xxl">
<Card isTile padding="s" radius="s">
<Layout.Stack
direction="row"
justifyContent="space-between"
alignItems="center"
gap="xs">
<Layout.Stack direction="row" alignItems="center" gap="s">
<Icon size="m" icon={IconReact} />
<Typography.Text
variant="m-400"
color="--color-fgcolor-neutral-primary">
{$createPlatform.name} ({$createPlatform.key})
</Typography.Text>
</Layout.Stack>
</Layout.Stack>
</Card>
</Layout.Stack>
{/if}
<!-- Step Three -->
{#if isPlatformCreated}
<Fieldset legend="Clone starter">
<Layout.Stack gap="l">
<Typography.Text variant="m-500">
1. Clone the starter kit from GitHub using the terminal or VSCode.
</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="bash" lineNumbers code={gitCloneCode} />
</div>
<Typography.Text variant="m-500"
>2. Open the file <InlineCode
size="s"
code="lib/constants/appwrite.js" /> and update the configuration settings.</Typography.Text>
<!-- Temporary fix: Remove this div once Code splitting issue with stack spacing is resolved -->
<div class="pink2-code-margin-fix">
<Code lang="javascript" lineNumbers code={updateConfigCode} />
</div>
<Typography.Text variant="m-500"
>3. Run the app on a connected device or simulator, then click the <InlineCode
size="s"
code="Send a ping" /> button to verify the setup.</Typography.Text>
</Layout.Stack>
</Fieldset>
{/if}
</Layout.Stack>
</Form>
<svelte:fragment slot="aside">
<Card padding="l" class="responsive-padding">
<Layout.Stack gap="xxl">
<Layout.Stack direction="row" justifyContent="center" gap="none">
<OnboardingPlatformCard iconSize={2.526} iconColor="#61DBFB" icon={IconReact} />
<ConnectionLine status={connectionSuccessful} />
<OnboardingPlatformCard
iconSize={2.526}
iconColor="#FD366E"
icon={IconAppwrite} />
</Layout.Stack>
<Layout.Stack direction="row" justifyContent="center" alignItems="center" gap="l">
{#if !connectionSuccessful}
<Spinner />
<Typography.Text variant="m-400">Waiting for connection...</Typography.Text>
{:else}
<!-- cannot apply fade on components -->
<div
in:fade={{ duration: 2500 }}
class="u-flex u-flex-vertical u-cross-center u-gap-8">
<Typography.Title size="m">Congratulations!</Typography.Title>
<Typography.Text variant="m-400"
>You connected your app successfully.</Typography.Text>
</div>
{/if}
</Layout.Stack>
</Layout.Stack>
</Card>
</svelte:fragment>
<svelte:fragment slot="footer">
<Button
size="s"
fullWidthMobile
secondary
disabled={isCreatingPlatform}
href={`${base}/project-${projectId}/overview`}>
Go to dashboard
</Button>
</svelte:fragment>
</Wizard>
<style lang="scss">
:global(.pink2-code-margin-fix pre) {
margin: revert;
}
:global(.responsive-padding) {
@media (max-width: 768px) {
padding: 16px;
}
}
</style>
@@ -1,47 +0,0 @@
<script lang="ts">
import { WizardWithSteps } from '$lib/layout';
import { invalidate } from '$app/navigation';
import { wizard } from '$lib/stores/wizard';
import { createPlatform } from './wizard/store';
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
import Step1 from './wizard/web/step1.svelte';
import Step2 from './wizard/web/step2.svelte';
import Step3 from './wizard/web/step3.svelte';
import Step4 from './wizard/step4.svelte';
import { Dependencies } from '$lib/constants';
async function onFinish() {
await Promise.all([invalidate(Dependencies.PROJECT), invalidate(Dependencies.PLATFORMS)]);
createPlatform.reset();
wizard.hide();
}
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Settings',
component: Step1
});
stepsComponents.set(2, {
label: 'Install',
component: Step2,
optional: true
});
stepsComponents.set(3, {
label: 'Import',
component: Step3,
optional: true
});
stepsComponents.set(4, {
label: 'Build',
component: Step4,
optional: true
});
</script>
<WizardWithSteps
title="Add a web platform"
steps={stepsComponents}
on:finish={onFinish}
on:exit={onFinish}
finalAction="Go to dashboard" />
@@ -1,60 +0,0 @@
<script lang="ts">
import { page } from '$app/stores';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { createPlatform } from '../store';
import { Submit, trackEvent } from '$lib/actions/analytics';
import { PlatformType } from '@appwrite.io/console';
const projectId = $page.params.project;
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdk.forConsole.projects.updatePlatform(
projectId,
$createPlatform.$id,
$createPlatform.name,
$createPlatform.key || undefined,
$createPlatform.store || undefined,
$createPlatform.hostname || undefined
);
return;
}
const platform = await sdk.forConsole.projects.createPlatform(
projectId,
PlatformType.Android,
$createPlatform.name,
$createPlatform.key || undefined,
undefined,
undefined
);
trackEvent(Submit.PlatformCreate, {
type: 'android'
});
$createPlatform.$id = platform.$id;
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">Android registration</svelte:fragment>
<FormList>
<InputText
id="name"
label="Name"
placeholder="My Android App"
required
bind:value={$createPlatform.name} />
<InputText
id="key"
label="Package Name"
placeholder="com.company.appname"
tooltip="Your package name is generally the applicationId in your app-level build.gradle file."
required
bind:value={$createPlatform.key} />
</FormList>
</WizardStep>
@@ -1,18 +0,0 @@
<script lang="ts">
import { Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { versions } from '../store';
const example1 = `repositories {
mavenCentral()
}`;
const example2 = `implementation("io.appwrite:sdk-for-android:${$versions['client-android']}")`;
</script>
<WizardStep>
<svelte:fragment slot="title">Install</svelte:fragment>
<p>First, add this to your root level <code class="inline-code">build.gradle</code> file.</p>
<Code label="Groovy" labelIcon="android" language="kotlin" code={example1} withCopy />
<p class="common-section">And add this to your project's build.gradle file.</p>
<Code label="Groovy" labelIcon="android" language="kotlin" code={example2} withCopy />
</WizardStep>
@@ -1,41 +0,0 @@
<script lang="ts">
import { Code } from '$lib/components';
import Id from '$lib/components/id.svelte';
import { WizardStep } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { isCloud } from '$lib/system';
const { endpoint, project } = sdk.forProject.client.config;
const code = `import io.appwrite.Client
import io.appwrite.services.Account
${
isCloud
? `val client = Client(context).setProject("${project}")`
: `val client = Client(context)
.setEndpoint("${endpoint}")
.setProject("${project}")
.setSelfSigned(status: true) // For self signed certificates, only use for development`
}`;
</script>
<WizardStep>
<svelte:fragment slot="title">Initialize</svelte:fragment>
<h2 class="heading-level-7">Initialize your SDK</h2>
<p>
Initialize your SDK by pointing the client to your Appwrite project using your <Id
value={project}>Project ID</Id
>.
</p>
<div class="u-margin-block-start-16">
<Code
label="Android SDK"
labelIcon="android"
language="kotlin"
{code}
withCopy
withLineNumbers
noMargin />
</div>
</WizardStep>
@@ -1,83 +0,0 @@
<script lang="ts">
import { page } from '$app/stores';
import { Pill } from '$lib/elements';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { createPlatform } from '../store';
import { Submit, trackEvent } from '$lib/actions/analytics';
import { PlatformType } from '@appwrite.io/console';
let platform: PlatformType = PlatformType.Appleios;
const projectId = $page.params.project;
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdk.forConsole.projects.deletePlatform(projectId, $createPlatform.$id);
}
const response = await sdk.forConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
$createPlatform.key,
undefined,
undefined
);
trackEvent(Submit.PlatformCreate, {
type: platform
});
$createPlatform.$id = response.$id;
$createPlatform.type = platform;
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">Apple registration</svelte:fragment>
<FormList>
<p>Choose an Apple platform</p>
<div class="u-flex u-gap-16 u-margin-block-start-8">
<Pill
button
on:click={() => (platform = PlatformType.Appleios)}
selected={platform === PlatformType.Appleios}>
iOS
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Applemacos)}
selected={platform === PlatformType.Applemacos}>
macOS
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Applewatchos)}
selected={platform === PlatformType.Applewatchos}>
watchOS
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Appletvos)}
selected={platform === PlatformType.Appletvos}>
tvOS
</Pill>
</div>
<InputText
id="name"
label="Name"
placeholder="My Apple App"
required
bind:value={$createPlatform.name} />
<InputText
id="hostname"
label="Bundle ID"
placeholder="com.company.appname"
tooltip="You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
required
bind:value={$createPlatform.key} />
</FormList>
</WizardStep>
@@ -1,81 +0,0 @@
<script lang="ts">
import { Code } from '$lib/components';
import { Pill } from '$lib/elements';
import { WizardStep } from '$lib/layout';
import { versions } from '../store';
enum Method {
Xcode,
Swift
}
let method: Method = Method.Xcode;
const example1 = `dependencies: [
.package(
name: "Appwrite",
url: "https://github.com/appwrite/sdk-for-swift",
.exact("${$versions['client-apple']}")
)
]')`;
const example2 = `targets: [
.target(
name: "[YOUR_TARGET]",
dependencies: [
"Appwrite"
]
)
]`;
</script>
<WizardStep>
<svelte:fragment slot="title">Install</svelte:fragment>
<div class="u-flex u-gap-16 u-margin-block-start-8">
<Pill button on:click={() => (method = Method.Xcode)} selected={method === Method.Xcode}>
Xcode
</Pill>
<Pill button on:click={() => (method = Method.Swift)} selected={method === Method.Swift}>
Swift Packages
</Pill>
</div>
<div class="common-section">
{#if method === Method.Xcode}
<ol class="numeric-list">
<li class="numeric-list-item">
<span class="text">
In the menu bar under Select File, select Add Packages
</span>
</li>
<li class="numeric-list-item">
<span class="text">
Search for the Appwrite SDK with the URL
<a class="link" href="https://github.com/appwrite/sdk-for-apple">
https://github.com/appwrite/sdk-for-apple
</a>
</span>
</li>
<li class="numeric-list-item">
<span class="text"
>In the right panel, select your target project and add your desired version
rules</span>
</li>
<li class="numeric-list-item">
<span class="text">
Select Add Package and wait for package resolution to complete
</span>
</li>
<li class="numeric-list-item">
<span class="text">
Make sure the Appwrite package product is checked and select Add Package
again
</span>
</li>
</ol>
{:else if method === Method.Swift}
<p>Add this to your <code class="inline-code">Package.swift</code> file.</p>
<Code withCopy withLineNumbers label="Swift" language="swift" code={example1} />
<p class="common-section">Then add the dependency to your target.</p>
<Code withCopy withLineNumbers label="Swift" language="swift" code={example2} />
{/if}
</div>
</WizardStep>
@@ -1,48 +0,0 @@
<script lang="ts">
import { Alert, Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { isCloud } from '$lib/system';
import { sdk } from '$lib/stores/sdk';
import Id from '$lib/components/id.svelte';
const { endpoint, project } = sdk.forProject.client.config;
const code = `import Appwrite
${
isCloud
? `let client = Client().setProject("${project}")`
: `let client = Client()
.setEndpoint("${endpoint}")
.setProject("${project}")
.setSelfSigned(true) // For self signed certificates, only use for development`
}`;
let showAlert = true;
</script>
<WizardStep>
<svelte:fragment slot="title">Initialize</svelte:fragment>
<h2 class="heading-level-7">Initialize your SDK</h2>
<p>
Initialize your SDK by pointing the client to your Appwrite project using your
<Id value={project}>Project ID</Id>
.
</p>
<Code label="Apple SDK" labelIcon="apple" language="swift" {code} withCopy withLineNumbers />
<p class="u-margin-block-start-24">
Before sending any API calls to your new Appwrite project, make sure your device or emulator
has network access to your Appwrite project's hostname or IP address.
</p>
{#if showAlert && !isCloud}
<div class="common-section">
<Alert type="info" dismissible on:dismiss={() => (showAlert = false)}>
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
you should use the private IP of the device running your Appwrite project as the hostname
of the endpoint instead of localhost. You can also use a service like ngrok to proxy
the Appwrite server.
</Alert>
</div>
{/if}
</WizardStep>
@@ -1,199 +0,0 @@
<script lang="ts">
import { page } from '$app/stores';
import { Pill } from '$lib/elements';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { createPlatform } from '../store';
import { Submit, trackEvent } from '$lib/actions/analytics';
import { PlatformType } from '@appwrite.io/console';
import { isValueOfStringEnum } from '$lib/helpers/types';
// enum Platform {
// Android = 'flutter-android',
// Ios = 'flutter-ios',
// Linux = 'flutter-linux',
// Macos = 'flutter-macos',
// Windows = 'flutter-windows',
// Web = 'flutter-web'
// }
// function isPlatform(value: string): value is Platform {
// return Object.values(Platform).includes(value as Platform);
// }
let platform: PlatformType = isValueOfStringEnum(PlatformType, $createPlatform.type)
? $createPlatform.type
: PlatformType.Flutterandroid;
const projectId = $page.params.project;
const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.io'];
const placeholder: Partial<
Record<
PlatformType,
{
name: string;
hostname: string;
tooltip: string;
}
>
> = {
[PlatformType.Flutterandroid]: {
name: 'My Android App',
hostname: 'com.company.appname',
tooltip:
'Your package name is generally the applicationId in your app-level build.gradle file.'
},
[PlatformType.Flutterios]: {
name: 'My iOS App',
hostname: 'com.company.appname',
tooltip:
"You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
},
[PlatformType.Flutterlinux]: {
name: 'My Linux App',
hostname: 'appname',
tooltip: 'Your application name'
},
[PlatformType.Fluttermacos]: {
name: 'My mac OS App',
hostname: 'com.company.appname',
tooltip:
"You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
},
[PlatformType.Flutterweb]: {
name: 'My Web App',
hostname: 'localhost',
tooltip:
'The hostname that your website will use to interact with the Appwrite APIs in production or development environments. No protocol or port number required.'
},
[PlatformType.Flutterwindows]: {
name: 'My Windows App',
hostname: 'appname',
tooltip: 'Your application name'
}
};
const hostname: Partial<Record<PlatformType, string>> = {
[PlatformType.Flutterandroid]: 'Package Name',
[PlatformType.Flutterios]: 'Bundle ID',
[PlatformType.Flutterlinux]: 'Package Name',
[PlatformType.Fluttermacos]: 'Bundle ID',
[PlatformType.Flutterweb]: 'Hostname',
[PlatformType.Flutterwindows]: 'Package Name'
};
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdk.forConsole.projects.deletePlatform(projectId, $createPlatform.$id);
}
const response = await sdk.forConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
platform !== PlatformType.Flutterweb ? $createPlatform.key : undefined,
undefined,
platform === PlatformType.Flutterweb ? $createPlatform.hostname : undefined
);
trackEvent(Submit.PlatformCreate, {
type: platform
});
$createPlatform.$id = response.$id;
$createPlatform.type = platform;
}
$: registee = {
[PlatformType.Flutterandroid]: 'Package name',
[PlatformType.Flutterios]: 'Bundle ID',
[PlatformType.Flutterlinux]: 'Package name',
[PlatformType.Fluttermacos]: 'Bundle ID',
[PlatformType.Flutterwindows]: 'Package name',
[PlatformType.Flutterweb]: 'Hostname'
}[platform];
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">{registee} registration</svelte:fragment>
<svelte:fragment slot="subtitle">
<div class="u-flex u-gap-16 u-margin-block-start-8 u-flex-wrap">
<Pill
button
on:click={() => (platform = PlatformType.Flutterandroid)}
selected={platform === PlatformType.Flutterandroid}>
Android
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Flutterios)}
selected={platform === PlatformType.Flutterios}>
iOS
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Flutterlinux)}
selected={platform === PlatformType.Flutterlinux}>
Linux
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Fluttermacos)}
selected={platform === PlatformType.Fluttermacos}>
macOS
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Flutterwindows)}
selected={platform === PlatformType.Flutterwindows}>
Windows
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Flutterweb)}
selected={platform === PlatformType.Flutterweb}>
Web
</Pill>
</div>
</svelte:fragment>
<FormList isCommonSection>
<InputText
id="name"
label="Name"
placeholder={placeholder[platform].name}
required
bind:value={$createPlatform.name} />
{#if platform === PlatformType.Flutterweb}
<div>
<InputText
id="hostname"
label={hostname[platform]}
placeholder={placeholder[platform].hostname}
tooltip={placeholder[platform].tooltip}
required
bind:value={$createPlatform.hostname} />
<div class="u-flex u-gap-16 u-margin-block-start-8">
{#each suggestions as suggestion}
<Pill
button
selected={$createPlatform.hostname === suggestion}
on:click={() => ($createPlatform.hostname = suggestion)}>
{suggestion}
</Pill>
{/each}
</div>
</div>
{:else}
<InputText
id="key"
label={hostname[platform]}
placeholder={placeholder[platform].hostname}
tooltip={placeholder[platform].tooltip}
required
bind:value={$createPlatform.key} />
{/if}
</FormList>
</WizardStep>
@@ -1,25 +0,0 @@
<script lang="ts">
import { Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { versions } from '../store';
const example1 = `dependencies:
appwrite: ^${$versions['client-flutter']}`;
const example2 = `flutter pub add appwrite`;
</script>
<WizardStep>
<svelte:fragment slot="title">Install</svelte:fragment>
<p>
Add Appwrite SDK to your package's <code class="inline-code">pubspec.yaml</code> file. You can
view an example here.
</p>
<Code label="YAML" language="yml" code={example1} withCopy />
<p class="common-section">
You can also install the SDK using the Dart package manager from your terminal.
</p>
<div class="u-margin-block-start-16">
<Code label="Bash" language="sh" code={example2} withCopy noMargin />
</div>
</WizardStep>
@@ -1,57 +0,0 @@
<script lang="ts">
import { Alert, Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { isCloud } from '$lib/system';
import { sdk } from '$lib/stores/sdk';
import Id from '$lib/components/id.svelte';
const { endpoint, project } = sdk.forProject.client.config;
const code = `import 'package:appwrite/appwrite.dart';
Client client = Client();
${
isCloud
? `client.setProject('${project}');`
: `client
.setEndpoint('${endpoint}')
.setProject('${project}')
.setSelfSigned(status: true); // For self signed certificates, only use for development;`
}`;
let showAlert = true;
</script>
<WizardStep>
<svelte:fragment slot="title">Initialize</svelte:fragment>
<h2 class="heading-level-7">Initialize your SDK</h2>
<p data-private>
Initialize your SDK by pointing the client to your Appwrite project using your
<Id value={project}>Project ID</Id>
</p>
<div class="u-margin-block-start-16">
<Code
label="Flutter SDK"
labelIcon="flutter"
language="dart"
{code}
withCopy
withLineNumbers
noMargin />
</div>
<p class="common-section">
Before sending any API calls to your new Appwrite project, make sure your device or emulator
has network access to your Appwrite project's hostname or IP address.
</p>
{#if showAlert && !isCloud}
<div class="common-section">
<Alert type="info" on:dismiss={() => (showAlert = false)}>
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
you should use the private IP of the device running your Appwrite project as the hostname
of the endpoint instead of localhost. You can also use a service like ngrok to proxy
the Appwrite server.
</Alert>
</div>
{/if}
</WizardStep>
@@ -1,106 +0,0 @@
<script lang="ts">
import { page } from '$app/stores';
import { Pill } from '$lib/elements';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { createPlatform } from '../store';
import { Submit, trackEvent } from '$lib/actions/analytics';
import { PlatformType } from '@appwrite.io/console';
import { isValueOfStringEnum } from '$lib/helpers/types';
let platform: PlatformType = isValueOfStringEnum(PlatformType, $createPlatform.type)
? $createPlatform.type
: PlatformType.Reactnativeandroid;
const projectId = $page.params.project;
const placeholder: Partial<
Record<
PlatformType,
{
name: string;
hostname: string;
tooltip: string;
}
>
> = {
[PlatformType.Reactnativeandroid]: {
name: 'My Android App',
hostname: 'com.company.appname',
tooltip:
'Your package name is generally the applicationId in your app-level build.gradle file.'
},
[PlatformType.Reactnativeios]: {
name: 'My iOS App',
hostname: 'com.company.appname',
tooltip:
"You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."
}
};
const hostname: Partial<Record<PlatformType, string>> = {
[PlatformType.Reactnativeandroid]: 'Package Name',
[PlatformType.Reactnativeios]: 'Bundle ID'
};
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdk.forConsole.projects.deletePlatform(projectId, $createPlatform.$id);
}
const response = await sdk.forConsole.projects.createPlatform(
projectId,
platform,
$createPlatform.name,
$createPlatform.key
);
trackEvent(Submit.PlatformCreate, {
type: platform
});
$createPlatform.$id = response.$id;
$createPlatform.type = platform;
}
$: registee = {
[PlatformType.Reactnativeandroid]: 'Package name',
[PlatformType.Reactnativeios]: 'Bundle ID'
}[platform];
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">{registee} registration</svelte:fragment>
<svelte:fragment slot="subtitle">
<div class="u-flex u-gap-16 u-margin-block-start-8 u-flex-wrap">
<Pill
button
on:click={() => (platform = PlatformType.Reactnativeandroid)}
selected={platform === PlatformType.Reactnativeandroid}>
Android
</Pill>
<Pill
button
on:click={() => (platform = PlatformType.Reactnativeios)}
selected={platform === PlatformType.Reactnativeios}>
iOS
</Pill>
</div>
</svelte:fragment>
<FormList isCommonSection>
<InputText
id="name"
label="Name"
placeholder={placeholder[platform].name}
required
bind:value={$createPlatform.name} />
<InputText
id="key"
label={hostname[platform]}
placeholder={placeholder[platform].hostname}
tooltip={placeholder[platform].tooltip}
required
bind:value={$createPlatform.key} />
</FormList>
</WizardStep>
@@ -1,13 +0,0 @@
<script lang="ts">
import { Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
const example = `npx expo install react-native-appwrite react-native-url-polyfill`;
</script>
<WizardStep>
<svelte:fragment slot="title">Install</svelte:fragment>
<p>Install the Appwrite SDK for React Native and required dependencies.</p>
<Code label="Bash" language="sh" code={example} withCopy />
</WizardStep>
@@ -1,58 +0,0 @@
<script lang="ts">
import { Alert, Code } from '$lib/components';
import { WizardStep } from '$lib/layout';
import { isCloud } from '$lib/system';
import { sdk } from '$lib/stores/sdk';
import { createPlatform } from '../store';
import Id from '$lib/components/id.svelte';
const { endpoint, project } = sdk.forProject.client.config;
const code = `import { Client, Account, ID } from 'react-native-appwrite';
const client = new Client()${
isCloud
? ''
: `
.setEndpoint('${endpoint}')`
}
.setProject('${project}')
.setPlatform('${$createPlatform.key}');
`;
let showAlert = true;
</script>
<WizardStep>
<svelte:fragment slot="title">Initialize</svelte:fragment>
<h2 class="heading-level-7">Initialize your SDK</h2>
<p data-private>
Initialize your SDK by pointing the client to your Appwrite project using your <Id
value={project}>Project ID</Id>
</p>
<div class="u-margin-block-start-16">
<Code
label="React Native"
labelIcon="code"
language="js"
{code}
withCopy
withLineNumbers
noMargin />
</div>
<p class="common-section">
Before sending any API calls to your new Appwrite project, make sure your device or emulator
has network access to your Appwrite project's hostname or IP address.
</p>
{#if showAlert && !isCloud}
<div class="common-section">
<Alert type="info" on:dismiss={() => (showAlert = false)}>
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
you should use the private IP of the device running your Appwrite project as the hostname
of the endpoint instead of localhost. You can also use a service like ngrok to proxy
the Appwrite server.
</Alert>
</div>
{/if}
</WizardStep>
@@ -1,84 +0,0 @@
<script lang="ts">
import { page } from '$app/stores';
import { Alert } from '$lib/components';
import { Pill } from '$lib/elements';
import { FormList, InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { createPlatform } from '../store';
import { Submit, trackEvent } from '$lib/actions/analytics';
import { PlatformType } from '@appwrite.io/console';
const projectId = $page.params.project;
const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.io'];
async function beforeSubmit() {
if ($createPlatform.$id) {
await sdk.forConsole.projects.updatePlatform(
projectId,
$createPlatform.$id,
$createPlatform.name,
$createPlatform.key || undefined,
$createPlatform.store || undefined,
$createPlatform.hostname || undefined
);
return;
}
const platform = await sdk.forConsole.projects.createPlatform(
projectId,
PlatformType.Web,
$createPlatform.name,
undefined,
undefined,
$createPlatform.hostname || undefined
);
trackEvent(Submit.PlatformCreate, {
type: 'web'
});
$createPlatform.$id = platform.$id;
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">Hostname registration</svelte:fragment>
<FormList>
<InputText
id="name"
label="Name"
placeholder="My Web App"
required
bind:value={$createPlatform.name} />
<div>
<InputText
id="hostname"
label="Hostname"
placeholder="localhost"
tooltip="The hostname that your website will use to interact with the Appwrite APIs in production or development environments. No protocol or port number required."
required
bind:value={$createPlatform.hostname} />
<div class="u-flex u-gap-16 u-margin-block-start-8">
{#each suggestions as suggestion}
<Pill
button
selected={$createPlatform.hostname === suggestion}
on:click={() => ($createPlatform.hostname = suggestion)}>
{suggestion}
</Pill>
{/each}
</div>
</div>
<Alert type="warning">
Using wildcard hostnames in production can become insecure. You can read about
<a
href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"
target="_blank"
rel="noopener noreferrer"
class="link">
Cross-Origin Resource Sharing (CORS)</a> for more information.
</Alert>
</FormList>
</WizardStep>
@@ -1,64 +0,0 @@
<script lang="ts">
import { versions } from '../store';
import { Code } from '$lib/components';
import { Pill } from '$lib/elements';
import { WizardStep } from '$lib/layout';
enum Method {
NPM,
CDN
}
let method: Method = Method.NPM;
const example1 = `import { Client } from 'appwrite';`;
const example2 =
`<script src="https://cdn.jsdelivr.net/npm/appwrite@${$versions['client-web']}"></script` +
`>\n` +
`<script>
const { Client } = Appwrite;
</script` +
`>`; // Prevent svelte from processing the closing script tag
</script>
<WizardStep>
<svelte:fragment slot="title">Install</svelte:fragment>
<svelte:fragment slot="subtitle">
Choose your preferred method of installation
<div class="u-flex u-gap-16 u-margin-block-start-8">
<Pill button on:click={() => (method = Method.NPM)} selected={method === Method.NPM}>
NPM
</Pill>
<Pill button on:click={() => (method = Method.CDN)} selected={method === Method.CDN}>
CDN
</Pill>
</div>
</svelte:fragment>
{#if method === Method.NPM}
<p>
Use <a
href="https://npmjs.com/package/appwrite"
target="_blank"
rel="noopener noreferrer"
class="link">NPM (node package manager)</a> from your command line to add Appwrite SDK
to your project.
</p>
<Code label="Bash" language="sh" code="npm install appwrite" withCopy />
<p class="common-section">
If you're using a bundler like <a
href="https://vitejs.dev"
target="_blank"
rel="noopener noreferrer"
class="link">Vite</a>
or
<a href="https://rollupjs.org" target="_blank" rel="noopener noreferrer" class="link"
>Rollup</a
>, import Appwrite as a module.
</p>
<Code label="Web SDK" labelIcon="code" language="js" code={example1} withCopy />
{:else if method === Method.CDN}
<p>Add the following script tags to install Appwrite with a CDN.</p>
<Code label="HTML" language="html" code={example2} withCopy />
{/if}
</WizardStep>
@@ -1,38 +0,0 @@
<script lang="ts">
import { Code } from '$lib/components';
import Id from '$lib/components/id.svelte';
import { WizardStep } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { isCloud } from '$lib/system';
const { endpoint, project } = sdk.forProject.client.config;
const code = `const client = new Client();
${
isCloud
? `client.setProject('${project}');`
: `client
.setEndpoint('${endpoint}')
.setProject('${project}');`
}`;
</script>
<WizardStep>
<svelte:fragment slot="title">Initialize SDK</svelte:fragment>
<h2 class="heading-level-7">Initialize your SDK</h2>
<p>
Initialize your SDK by pointing the client to your Appwrite project using your <Id
value={project}>Project ID</Id
>.
</p>
<div class="u-margin-block-start-16">
<Code
label="Web SDK"
labelIcon="code"
language="js"
{code}
withCopy
withLineNumbers
noMargin />
</div>
</WizardStep>