Skip to content

Commit 0c8c9d2

Browse files
authored
Merge pull request #1 from appwrite/feat-new-rn-starter-kit
React Native starter kit
2 parents 7fa8b7f + b405cd0 commit 0c8c9d2

30 files changed

+18988
-0
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# React Native starter kit with Appwrite
2+
3+
Kickstart your React Native development with this ready-to-use starter project integrated with [Appwrite](https://www.appwrite.io)
4+
5+
## πŸš€Getting started
6+
7+
###
8+
Clone the Project
9+
Clone this repository to your local machine using Git:
10+
11+
`git clone https://github.com/appwrite/starter-for-react-native`
12+
13+
## πŸ› οΈ Development guid
14+
1. **Configure Appwrite**<br/>
15+
Navigate to `.env` and update the values to match your Appwrite project credentials.
16+
2. **Customize as needed**<br/>
17+
Modify the starter kit to suit your app's requirements. Adjust UI, features, or backend
18+
integrations as per your needs.
19+
3. **Install dependencies**<br/>
20+
Run `npm install` to install all dependencies.
21+
4. **Run the app**<br/>
22+
Start the project by running `npx expo start`. Download [Expo Go](https://expo.dev/go) to run the app on your device.
23+
24+
## πŸ“¦ Building for production
25+
To create a production build of your app, follow the documentation by [Expo Application Services](https://expo.dev/eas#build)
26+
27+
## πŸ’‘ Additional notes
28+
- This starter project is designed to streamline your React Native development with Appwrite.
29+
- Refer to the [Appwrite documentation](https://appwrite.io/docs) for detailed integration guidance.

β€Žapp.jsonβ€Ž

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"expo": {
3+
"name": "starter-react-native",
4+
"slug": "starter-react-native",
5+
"version": "1.0.0",
6+
"orientation": "portrait",
7+
"icon": "./assets/images/icon.png",
8+
"scheme": "myapp",
9+
"userInterfaceStyle": "automatic",
10+
"newArchEnabled": true,
11+
"ios": {
12+
"supportsTablet": true
13+
},
14+
"android": {
15+
"adaptiveIcon": {
16+
"foregroundImage": "./assets/images/adaptive-icon.png",
17+
"backgroundColor": "#ffffff"
18+
}
19+
},
20+
"web": {
21+
"bundler": "metro",
22+
"output": "static",
23+
"favicon": "./assets/images/favicon.png"
24+
},
25+
"plugins": [
26+
"expo-router",
27+
[
28+
"expo-splash-screen",
29+
{
30+
"image": "./assets/images/splash-icon.png",
31+
"imageWidth": 200,
32+
"resizeMode": "contain",
33+
"backgroundColor": "#ffffff"
34+
}
35+
]
36+
],
37+
"experiments": {
38+
"typedRoutes": true
39+
}
40+
}
41+
}

β€Žapp/_layout.tsxβ€Ž

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Slot } from "expo-router";
2+
import { View } from "react-native";
3+
4+
export default function HomeLayout() {
5+
return (
6+
<View style={{ flex: 1, backgroundColor: "#FAFAFB" }}>
7+
<Slot />
8+
</View>
9+
);
10+
}

β€Žapp/index.tsxβ€Ž

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import { Platform, ScrollView, StyleSheet, Text, View } from "react-native";
2+
import { Header } from "@/components/Header";
3+
import { useRef, useState } from "react";
4+
import { Card } from "@/components/Card";
5+
import { fontStyles } from "@/styles/font";
6+
import { IconArrowSmRight } from "@/assets/images/IconArrowSmRight";
7+
import { Code } from "@/components/Code";
8+
import { Logs } from "@/components/Logs";
9+
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
10+
import { GestureHandlerRootView } from "react-native-gesture-handler";
11+
import { Log } from "@/types/log";
12+
import { AppwriteException, Client } from "appwrite";
13+
14+
const client = new Client()
15+
.setProject(process.env.EXPO_PUBLIC_APPWRITE_PROJECT_ID ?? "")
16+
.setEndpoint(process.env.EXPO_PUBLIC_APPWRITE_ENDPOINT ?? "");
17+
18+
export default function HomeScreen() {
19+
const [connectionState, setConnectionState] = useState<
20+
"idle" | "loading" | "success" | "error"
21+
>("idle");
22+
const bottomSheetRef = useRef<BottomSheet>(null);
23+
const [currentSnapIndex, setCurrentSnapIndex] = useState<number>(0);
24+
const [logs, setLogs] = useState<Array<Log>>([]);
25+
26+
const doPing = async () => {
27+
setConnectionState("loading");
28+
let log: Log;
29+
try {
30+
const res = await client.ping();
31+
log = {
32+
date: new Date(),
33+
method: "GET",
34+
path: "/v1/ping",
35+
status: 200,
36+
response: res,
37+
};
38+
setConnectionState("success");
39+
} catch (err) {
40+
log = {
41+
date: new Date(),
42+
method: "GET",
43+
path: "/v1/ping",
44+
status: err instanceof AppwriteException ? err.code : 500,
45+
response: err instanceof AppwriteException ? err.message : "unknown",
46+
};
47+
setConnectionState("error");
48+
}
49+
setLogs([...logs, log]);
50+
};
51+
52+
const toggleBottomSheet = () => {
53+
if (bottomSheetRef.current) {
54+
const newIndex = currentSnapIndex === 1 ? 0 : 1;
55+
setCurrentSnapIndex(newIndex);
56+
bottomSheetRef.current.snapToIndex(newIndex);
57+
}
58+
};
59+
60+
const handleSnapChange = (index: number) => {
61+
setCurrentSnapIndex(index);
62+
};
63+
64+
return (
65+
<View style={{ flex: 1 }}>
66+
<GestureHandlerRootView>
67+
<ScrollView>
68+
<Header pingFunction={doPing} state={connectionState} />
69+
<View style={styles.cardContainer}>
70+
<Card>
71+
<View style={styles.cardHeader}>
72+
<Text style={fontStyles.titleM}>Edit your app</Text>
73+
</View>
74+
<Text>
75+
<Code variant={"secondary"}>Edit </Code>
76+
<Code variant={"primary"}>app/index.tsx</Code>
77+
<Code variant={"secondary"}> to get started with building</Code>
78+
<Code variant={"secondary"}>
79+
your app and many more to come
80+
</Code>
81+
</Text>
82+
</Card>
83+
<Card href={"https://cloud.appwrite.io"}>
84+
<View style={styles.cardHeader}>
85+
<Text style={fontStyles.titleM}>Go to console</Text>
86+
<IconArrowSmRight />
87+
</View>
88+
<Text style={fontStyles.bodyM}>
89+
Navigate to the console to control and oversee the Appwrite
90+
services.
91+
</Text>
92+
</Card>
93+
<Card href={"https://appwrite.io/docs"}>
94+
<View style={styles.cardHeader}>
95+
<Text style={fontStyles.titleM}>Explore docs</Text>
96+
<IconArrowSmRight />
97+
</View>
98+
<Text style={fontStyles.bodyM}>
99+
Discover the full power of Appwrite by diving into our
100+
documentation.
101+
</Text>
102+
</Card>
103+
</View>
104+
</ScrollView>
105+
<BottomSheet
106+
index={0}
107+
snapPoints={[Platform.OS === "android" ? 50 : 70, "50%", "90%"]}
108+
enablePanDownToClose={false}
109+
handleComponent={null}
110+
ref={bottomSheetRef}
111+
onChange={handleSnapChange}
112+
>
113+
<BottomSheetView style={styles.bottomSheet}>
114+
<Logs
115+
toggleBottomSheet={toggleBottomSheet}
116+
isOpen={currentSnapIndex > 0}
117+
logs={logs}
118+
/>
119+
</BottomSheetView>
120+
</BottomSheet>
121+
</GestureHandlerRootView>
122+
</View>
123+
);
124+
}
125+
126+
const styles = StyleSheet.create({
127+
bottomSheet: {
128+
borderTopWidth: 1,
129+
minHeight: Platform.OS === "android" ? 50 : 70,
130+
flex: 1,
131+
borderColor: "#EDEDF0",
132+
},
133+
cardContainer: {
134+
paddingInline: 20,
135+
display: "flex",
136+
gap: 16,
137+
},
138+
scrollview: {
139+
height: 200,
140+
},
141+
cardHeader: {
142+
display: "flex",
143+
justifyContent: "space-between",
144+
flexDirection: "row",
145+
alignItems: "center",
146+
marginBottom: 8,
147+
},
148+
editDescription: {
149+
display: "flex",
150+
flexDirection: "row",
151+
justifyContent: "flex-start",
152+
},
153+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Svg, { Path } from "react-native-svg";
2+
3+
export const IconArrowSmRight = () => {
4+
return (
5+
<Svg width="24" height="24" viewBox="0 0 24 24" fill="none">
6+
<Path
7+
fill-rule="evenodd"
8+
clip-rule="evenodd"
9+
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"
10+
fill="#D8D8DB"
11+
/>
12+
</Svg>
13+
);
14+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Svg, { Path } from "react-native-svg";
2+
3+
export const IconChevronDown = () => {
4+
return (
5+
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
6+
<Path
7+
fill-rule="evenodd"
8+
clip-rule="evenodd"
9+
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"
10+
fill="#97979B"
11+
/>
12+
</Svg>
13+
);
14+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Svg, { Path } from "react-native-svg";
2+
3+
export const IconChevronUp = () => {
4+
return (
5+
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
6+
<Path
7+
fill-rule="evenodd"
8+
clip-rule="evenodd"
9+
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"
10+
fill="#97979B"
11+
/>
12+
</Svg>
13+
);
14+
};

β€Žassets/images/appwrite.pngβ€Ž

9.67 KB
Loading
30.9 KB
Loading
62.4 KB
Loading

0 commit comments

Comments
Β (0)