Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# React Native starter kit with Appwrite

Kickstart your React Native development with this ready-to-use starter project integrated with [Appwrite](https://www.appwrite.io)

## 🚀Getting started

###
Clone the Project
Clone this repository to your local machine using Git:

`git clone https://github.com/appwrite/starter-for-react-native`

## 🛠️ Development guid
1. **Configure Appwrite**<br/>
Navigate to `.env` and update the values to match your Appwrite project credentials.
2. **Customize as needed**<br/>
Modify the starter kit to suit your app's requirements. Adjust UI, features, or backend
integrations as per your needs.
3. **Install dependencies**<br/>
Run `npm install` to install all dependencies.
4. **Run the app**<br/>
Start the project by running `npx expo start`. Download [Expo Go](https://expo.dev/go) to run the app on your device.

## 📦 Building for production
To create a production build of your app, follow the documentation by [Expo Application Services](https://expo.dev/eas#build)

## 💡 Additional notes
- This starter project is designed to streamline your React Native development with Appwrite.
- Refer to the [Appwrite documentation](https://appwrite.io/docs) for detailed integration guidance.
41 changes: 41 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"expo": {
"name": "starter-react-native",
"slug": "starter-react-native",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "myapp",
"userInterfaceStyle": "automatic",
"newArchEnabled": true,
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}
]
],
"experiments": {
"typedRoutes": true
}
}
}
10 changes: 10 additions & 0 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Slot } from "expo-router";
import { View } from "react-native";

export default function HomeLayout() {
return (
<View style={{ flex: 1, backgroundColor: "#FAFAFB" }}>
<Slot />
</View>
);
}
153 changes: 153 additions & 0 deletions app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { Platform, ScrollView, StyleSheet, Text, View } from "react-native";
import { Header } from "@/components/Header";
import { useRef, useState } from "react";
import { Card } from "@/components/Card";
import { fontStyles } from "@/styles/font";
import { IconArrowSmRight } from "@/assets/images/IconArrowSmRight";
import { Code } from "@/components/Code";
import { Logs } from "@/components/Logs";
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { Log } from "@/types/log";
import { AppwriteException, Client } from "appwrite";

const client = new Client()
.setProject(process.env.EXPO_PUBLIC_APPWRITE_PROJECT_ID ?? "")
.setEndpoint(process.env.EXPO_PUBLIC_APPWRITE_ENDPOINT ?? "");

export default function HomeScreen() {
const [connectionState, setConnectionState] = useState<
"idle" | "loading" | "success" | "error"
>("idle");
const bottomSheetRef = useRef<BottomSheet>(null);
const [currentSnapIndex, setCurrentSnapIndex] = useState<number>(0);
const [logs, setLogs] = useState<Array<Log>>([]);

const doPing = async () => {
setConnectionState("loading");
let log: Log;
try {
const res = await client.ping();
log = {
date: new Date(),
method: "GET",
path: "/v1/ping",
status: 200,
response: res,
};
setConnectionState("success");
} catch (err) {
log = {
date: new Date(),
method: "GET",
path: "/v1/ping",
status: err instanceof AppwriteException ? err.code : 500,
response: err instanceof AppwriteException ? err.message : "unknown",
};
setConnectionState("error");
}
setLogs([...logs, log]);
};

const toggleBottomSheet = () => {
if (bottomSheetRef.current) {
const newIndex = currentSnapIndex === 1 ? 0 : 1;
setCurrentSnapIndex(newIndex);
bottomSheetRef.current.snapToIndex(newIndex);
}
};

const handleSnapChange = (index: number) => {
setCurrentSnapIndex(index);
};

return (
<View style={{ flex: 1 }}>
<GestureHandlerRootView>
<ScrollView>
<Header pingFunction={doPing} state={connectionState} />
<View style={styles.cardContainer}>
<Card>
<View style={styles.cardHeader}>
<Text style={fontStyles.titleM}>Edit your app</Text>
</View>
<Text>
<Code variant={"secondary"}>Edit </Code>
<Code variant={"primary"}>app/index.tsx</Code>
<Code variant={"secondary"}> to get started with building</Code>
<Code variant={"secondary"}>
your app and many more to come
</Code>
</Text>
</Card>
<Card href={"https://cloud.appwrite.io"}>
<View style={styles.cardHeader}>
<Text style={fontStyles.titleM}>Go to console</Text>
<IconArrowSmRight />
</View>
<Text style={fontStyles.bodyM}>
Navigate to the console to control and oversee the Appwrite
services.
</Text>
</Card>
<Card href={"https://appwrite.io/docs"}>
<View style={styles.cardHeader}>
<Text style={fontStyles.titleM}>Explore docs</Text>
<IconArrowSmRight />
</View>
<Text style={fontStyles.bodyM}>
Discover the full power of Appwrite by diving into our
documentation.
</Text>
</Card>
</View>
</ScrollView>
<BottomSheet
index={0}
snapPoints={[Platform.OS === "android" ? 50 : 70, "50%", "90%"]}
enablePanDownToClose={false}
handleComponent={null}
ref={bottomSheetRef}
onChange={handleSnapChange}
>
<BottomSheetView style={styles.bottomSheet}>
<Logs
toggleBottomSheet={toggleBottomSheet}
isOpen={currentSnapIndex > 0}
logs={logs}
/>
</BottomSheetView>
</BottomSheet>
</GestureHandlerRootView>
</View>
);
}

const styles = StyleSheet.create({
bottomSheet: {
borderTopWidth: 1,
minHeight: Platform.OS === "android" ? 50 : 70,
flex: 1,
borderColor: "#EDEDF0",
},
cardContainer: {
paddingInline: 20,
display: "flex",
gap: 16,
},
scrollview: {
height: 200,
},
cardHeader: {
display: "flex",
justifyContent: "space-between",
flexDirection: "row",
alignItems: "center",
marginBottom: 8,
},
editDescription: {
display: "flex",
flexDirection: "row",
justifyContent: "flex-start",
},
});
14 changes: 14 additions & 0 deletions assets/images/IconArrowSmRight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Svg, { Path } from "react-native-svg";

export const IconArrowSmRight = () => {
return (
<Svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<Path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.3513 6.35147C12.8199 5.88284 13.5797 5.88284 14.0483 6.35147L18.8483 11.1515C19.317 11.6201 19.317 12.3799 18.8483 12.8485L14.0483 17.6485C13.5797 18.1172 12.8199 18.1172 12.3513 17.6485C11.8826 17.1799 11.8826 16.4201 12.3513 15.9515L15.1027 13.2L5.99981 13.2C5.33706 13.2 4.7998 12.6627 4.7998 12C4.7998 11.3373 5.33706 10.8 5.99981 10.8H15.1027L12.3513 8.04853C11.8826 7.5799 11.8826 6.8201 12.3513 6.35147Z"
fill="#D8D8DB"
/>
</Svg>
);
};
14 changes: 14 additions & 0 deletions assets/images/IconChevronDown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Svg, { Path } from "react-native-svg";

export const IconChevronDown = () => {
return (
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<Path
fill-rule="evenodd"
clip-rule="evenodd"
d="M14.7071 7.29289C14.3166 6.90237 13.6834 6.90237 13.2929 7.29289L10 10.5858L6.70711 7.29289C6.31658 6.90237 5.68342 6.90237 5.29289 7.29289C4.90237 7.68342 4.90237 8.31658 5.29289 8.70711L9.29289 12.7071C9.68342 13.0976 10.3166 13.0976 10.7071 12.7071L14.7071 8.70711C15.0976 8.31658 15.0976 7.68342 14.7071 7.29289Z"
fill="#97979B"
/>
</Svg>
);
};
14 changes: 14 additions & 0 deletions assets/images/IconChevronUp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Svg, { Path } from "react-native-svg";

export const IconChevronUp = () => {
return (
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<Path
fill-rule="evenodd"
clip-rule="evenodd"
d="M5.29289 12.7071C5.68342 13.0976 6.31658 13.0976 6.70711 12.7071L10 9.41421L13.2929 12.7071C13.6834 13.0976 14.3166 13.0976 14.7071 12.7071C15.0976 12.3166 15.0976 11.6834 14.7071 11.2929L10.7071 7.29289C10.3166 6.90237 9.68342 6.90237 9.29289 7.29289L5.29289 11.2929C4.90237 11.6834 4.90237 12.3166 5.29289 12.7071Z"
fill="#97979B"
/>
</Svg>
);
};
Binary file added assets/images/appwrite.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/appwrite@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/appwrite@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/grid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/grid@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/grid@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/rn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/rn@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/rn@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/splash-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { View, Text, StyleSheet, TouchableOpacity } from "react-native";

interface ButtonProps {
text: string;
onPress: () => void;
}

export const Button = ({ text, onPress }: ButtonProps) => {
return (
<TouchableOpacity onPress={onPress}>
<View style={styles.container}>
<Text style={styles.text}>{text}</Text>
</View>
</TouchableOpacity>
);
};

const styles = StyleSheet.create({
container: {
backgroundColor: "#FD366E",
paddingBlock: 10,
paddingHorizontal: 12,
borderRadius: 8,
},
text: {
color: "#FFF",
fontWeight: 500,
fontSize: 14,
lineHeight: 20,
},
});
33 changes: 33 additions & 0 deletions components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ReactNode } from "react";
import { Linking, StyleSheet, TouchableOpacity, View } from "react-native";

interface CardProps {
children: ReactNode;
href?: string;
}

export const Card = ({ children, href }: CardProps) => {
if (href) {
return (
<TouchableOpacity
onPress={() => {
Linking.openURL(href);
}}
>
<View style={styles.card}>{children}</View>
</TouchableOpacity>
);
}
return <View style={styles.card}>{children}</View>;
};

const styles = StyleSheet.create({
card: {
flex: 1,
backgroundColor: "#FFF",
borderColor: "#EDEDF0",
borderWidth: 1,
borderRadius: 8,
padding: 16,
},
});
37 changes: 37 additions & 0 deletions components/Code.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { StyleSheet, Text, View } from "react-native";

interface CodeProps {
children: string;
variant: "primary" | "secondary";
}
export const Code = ({ children, variant }: CodeProps) => {
return (
<View
style={
variant === "primary"
? styles.codeContainer
: styles.codeContainerSecondary
}
>
<Text
style={{
...styles.code,
color: variant === "secondary" ? "#56565C" : "inherit",
}}
>
{children}
</Text>
</View>
);
};
const styles = StyleSheet.create({
codeContainer: {
paddingInline: 6,
borderRadius: 4,
backgroundColor: "#EDEDF0",
},
codeContainerSecondary: {},
code: {
fontSize: 14,
},
});
Loading