├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── media ├── authflow.png ├── bottomtabs.gif ├── hero.png ├── midtrans.gif ├── thumbnail.gif └── withnav.gif ├── template-typescript-bottom-tabs-supabase-auth-flow ├── .gitignore ├── App.tsx ├── README.md ├── app.json ├── assets │ ├── adaptive-icon.png │ ├── favicon.png │ ├── fonts │ │ └── SpaceMono-Regular.ttf │ ├── icon.png │ ├── images │ │ ├── adaptive-icon.png │ │ ├── favicon.png │ │ ├── forget.png │ │ ├── icon.png │ │ ├── login.png │ │ ├── register.png │ │ └── splash.png │ └── splash.png ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ ├── components │ │ └── utils │ │ │ ├── TabBarIcon.tsx │ │ │ └── TabBarText.tsx │ ├── initSupabase.ts │ ├── navigation │ │ ├── AuthStack.tsx │ │ ├── MainStack.tsx │ │ ├── MainTabs.tsx │ │ └── index.tsx │ ├── provider │ │ └── AuthProvider.tsx │ ├── screens │ │ ├── About.tsx │ │ ├── Home.tsx │ │ ├── Profile.tsx │ │ ├── SecondScreen.tsx │ │ ├── auth │ │ │ ├── ForgetPassword.tsx │ │ │ ├── Login.tsx │ │ │ └── Register.tsx │ │ └── utils │ │ │ └── Loading.tsx │ └── types │ │ └── navigation.tsx └── tsconfig.json ├── template-typescript-bottom-tabs-with-auth-flow ├── .expo-shared │ └── assets.json ├── .gitignore ├── App.tsx ├── README.md ├── app.json ├── assets │ └── images │ │ ├── adaptive-icon.png │ │ ├── favicon.png │ │ ├── forget.png │ │ ├── icon.png │ │ ├── login.png │ │ ├── register.png │ │ └── splash.png ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ ├── components │ │ └── utils │ │ │ ├── TabBarIcon.tsx │ │ │ └── TabBarText.tsx │ ├── navigation │ │ ├── AuthStack.tsx │ │ ├── MainStack.tsx │ │ ├── MainTabs.tsx │ │ └── index.tsx │ ├── provider │ │ └── AuthProvider.tsx │ ├── screens │ │ ├── About.tsx │ │ ├── Home.tsx │ │ ├── Profile.tsx │ │ ├── SecondScreen.tsx │ │ ├── auth │ │ │ ├── ForgetPassword.tsx │ │ │ ├── Login.tsx │ │ │ └── Register.tsx │ │ └── utils │ │ │ └── Loading.tsx │ └── types │ │ └── navigation.tsx └── tsconfig.json ├── template-with-bottom-tabs-auth-flow ├── .expo-shared │ └── assets.json ├── .gitignore ├── App.js ├── README.md ├── app.json ├── assets │ ├── favicon.png │ ├── forget.png │ ├── icon.png │ ├── login.png │ ├── register.png │ └── splash.png ├── babel.config.js ├── package-lock.json ├── package.json └── src │ ├── components │ └── utils │ │ ├── TabBarIcon.js │ │ └── TabBarText.js │ ├── navigation │ └── AppNavigator.js │ ├── provider │ └── AuthProvider.js │ └── screens │ ├── About.js │ ├── Home.js │ ├── Profile.js │ ├── SecondScreen.js │ ├── auth │ ├── ForgetPassword.js │ ├── Login.js │ └── Register.js │ └── utils │ └── Loading.js ├── template-with-bottom-tabs ├── .expo-shared │ └── assets.json ├── .gitignore ├── App.js ├── README.md ├── app.json ├── assets │ ├── favicon.png │ ├── icon.png │ └── splash.png ├── babel.config.js ├── package-lock.json ├── package.json └── src │ ├── components │ └── utils │ │ ├── TabBarIcon.js │ │ └── TabBarText.js │ ├── navigation │ └── AppNavigator.js │ └── screens │ ├── About.js │ ├── Home.js │ ├── Profile.js │ └── SecondScreen.js ├── template-with-firebase-auth-flow ├── .expo-shared │ └── assets.json ├── .gitignore ├── App.js ├── README.md ├── app.json ├── assets │ ├── favicon.png │ ├── forget.png │ ├── icon.png │ ├── login.png │ ├── register.png │ └── splash.png ├── babel.config.js ├── package-lock.json ├── package.json └── src │ ├── navigation │ └── AppNavigator.js │ ├── provider │ └── AuthProvider.js │ └── screens │ ├── Home.js │ ├── SecondScreen.js │ ├── auth │ ├── ForgetPassword.js │ ├── Login.js │ └── Register.js │ └── utils │ └── Loading.js └── template-with-navigation ├── .expo-shared └── assets.json ├── .gitignore ├── App.js ├── README.md ├── app.json ├── assets ├── favicon.png ├── icon.png └── splash.png ├── babel.config.js ├── package-lock.json ├── package.json └── src ├── navigation └── AppNavigator.js └── screens ├── Home.js └── SecondScreen.js /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [codingki] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: kikiding 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: 13 | [ 14 | "https://karyakarsa.com/kikiding", 15 | ] 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.* 2 | *.jks 3 | *.p8 4 | *.p12 5 | *.key 6 | *.mobileprovision 7 | *.orig.* 8 | 9 | # macOS 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nur Fikri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native + Expo Starter Templates 2 | 3 | These are my starter templates or my way for building mobile app with react native and expo. I'm tired everytime I create a new project from blank, so I decided to make a starter templates, feel free to use it 🥳 4 | 5 | ## Preview 6 | 7 | ![media/thumbnail.gif](media/thumbnail.gif) 8 | 9 | If you are looking for react native midtrans example, I moved it [here](https://github.com/codingki/react-native-midtrans-example) 10 | 11 | **Firebase auth flow** 12 | ![media/authflow.png](media/authflow.png) 13 | 14 | ## Rapi UI 15 | 16 | ![media/hero.png](media/hero.png) 17 | 18 | These UI components are provided by [Rapi UI](https://rapi-ui.kikiding.space/). 19 | Check the [documentation](https://rapi-ui.kikiding.space/docs/) for usage and more components. 20 | 21 | ## Documentation 22 | 23 | ### Typescript 24 | 25 | - [Template bottom tabs with auth flow (Typescript)](https://github.com/codingki/react-native-expo-template/tree/master/template-typescript-bottom-tabs-with-auth-flow) 26 | - [Template bottom tabs with Supabase.io auth flow (Typescript)](https://github.com/codingki/react-native-expo-template/tree/master/template-typescript-bottom-tabs-supabase-auth-flow) 27 | 28 | ### Javascript 29 | 30 | - [Template Blank with navigation](https://github.com/codingki/react-native-expo-template/tree/master/template-with-navigation) 31 | - [Template Bottom tabs](https://github.com/codingki/react-native-expo-template/tree/master/template-with-bottom-tabs) 32 | - [Template Firebase auth flow](https://github.com/codingki/react-native-expo-template/tree/master/template-with-firebase-auth-flow) 33 | - [Template Bottom tabs with auth flow](https://github.com/codingki/react-native-expo-template/tree/master/template-with-bottom-tabs-auth-flow) 34 | 35 | ## Changelog 36 | 37 | **03/01/2022** 38 | 39 | - Upgrade Expo SDK to v44.0 (latest) 40 | - Upgrade Firebase from v8.x -> v9.x (latest) 41 | - Updgrade React navigation from v5.x -> v6.x (latest) 42 | 43 | **15/07/2021** 44 | 45 | - Fix firebase import error 46 | - Upgrade Expo SDK to v42.0 47 | 48 | **13/06/2021** 49 | 50 | - Template now has darkmode 51 | - Rapi UI updated to 0.2.1 52 | 53 | **25/04/2021** 54 | 55 | - Expo updated to SDK 41 56 | 57 | **24/03/2021** 58 | 59 | - Now all the UI components uses [Rapi UI](https://rapi-ui.kikiding.space/) 60 | - Remove some unused packages 61 | - Fixed some bugs and file managements moved to `src/` directory 62 | 63 | if you find these useful don't forget to give it a star ⭐ and share it to your friends ❤️ 64 | 65 | Reach me on [twitter](https://twitter.com/kikiding/) 66 | -------------------------------------------------------------------------------- /media/authflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/media/authflow.png -------------------------------------------------------------------------------- /media/bottomtabs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/media/bottomtabs.gif -------------------------------------------------------------------------------- /media/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/media/hero.png -------------------------------------------------------------------------------- /media/midtrans.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/media/midtrans.gif -------------------------------------------------------------------------------- /media/thumbnail.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/media/thumbnail.gif -------------------------------------------------------------------------------- /media/withnav.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/media/withnav.gif -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | 12 | # macOS 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/App.tsx: -------------------------------------------------------------------------------- 1 | import { StatusBar } from "expo-status-bar"; 2 | import React from "react"; 3 | import { ThemeProvider } from "react-native-rapi-ui"; 4 | import Navigation from "./src/navigation"; 5 | import { AuthProvider } from "./src/provider/AuthProvider"; 6 | 7 | export default function App() { 8 | const images = [ 9 | require("./assets/images/login.png"), 10 | require("./assets/images/register.png"), 11 | require("./assets/images/forget.png"), 12 | ]; 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/README.md: -------------------------------------------------------------------------------- 1 | # Template bottom tabs with auth flow (Typescript) 2 | 3 | Typescript Template starter with React Navigation Bottom Tabs and Supabase auth using React Context 4 | 5 | # Preview 6 | 7 | ![../media/authflow.png](../media/authflow.png) 8 | 9 | # Installation 10 | 11 | 1. Install [node.js](https://nodejs.org/en/) 12 | 2. Install Expo 13 | 14 | ```jsx 15 | npm install --global expo-cli 16 | ``` 17 | 18 | 3. Download this repo 19 | 4. Install deps on your template folder 20 | 21 | ```jsx 22 | npm install 23 | ``` 24 | 25 | 5. Start the environtment 26 | 27 | ```jsx 28 | expo start 29 | ``` 30 | 31 | # Auth Flow 32 | 33 | ### Supabase Setup 34 | 35 | - Set up a new Supabase.io project 36 | - Fill your supabase credentials to your config inside `./src/initSupabase.ts` 37 | - You can find your supabase credentials in your project -> settings -> API 38 | 39 | ```jsx 40 | // Better put your these secret keys in .env file 41 | export const supabase = createClient( 42 | "supabaseUrl", "supabaseKey", 43 | { 44 | localStorage: AsyncStorage as any, 45 | } 46 | ); 47 | ``` 48 | 49 | and you good to go! 50 | 51 | ### Prebuilt UI Screens 52 | 53 | There are 3 screens included inside `./src/screens/auth` and one more thing its included with the supabase auth function, so you don't need to create the function. The ilustrations I use [undraw](https://undraw.co/) 54 | 55 | - Login screen `./src/screens/auth/login.tsx` 56 | - Register screen `./src/screens/auth/register.tsx` 57 | - Forget password screen `./src/screens/auth/forget.tsx` 58 | 59 | ### React Navigation Auth Flow 60 | 61 | The checking logged users process is inside `./src/provider/AuthProvider` I use React Context, you can add more functions like get the data of the user and store it to the context (better static data, ex: uid) 62 | 63 | Inside the navigator `./src/navigation/AppNavigator.js` 64 | There's 2 stack navigator : 65 | 66 | - `` → for not logged in users stack 67 | - `
` → for logged in users stack 68 | - `` → when checking if the user is logged in or not loading screen 69 | 70 | ```jsx 71 | export default () => { 72 | const auth = useContext(AuthContext); 73 | const user = auth.user; 74 | return ( 75 | 76 | {user == null && } 77 | {user == false && } 78 | {user == true &&
} 79 | 80 | ); 81 | }; 82 | ``` 83 | 84 | # Rapi UI 85 | 86 | ![../media/hero.png](../media/hero.png) 87 | 88 | These UI components are provided by [Rapi UI](https://rapi-ui.kikiding.space/). 89 | Check the [documentation](https://rapi-ui.kikiding.space/docs/) for usage and more components. 90 | 91 | # File Managements 92 | 93 | These are the folders and the functionality all in `src/` 94 | 95 | ```jsx 96 | /src/assets -> for media such as images, etc 97 | /src/components -> for components 98 | /src/navigation -> for React Navigation 99 | /src/provider -> for React Context 100 | /src/screens -> for Screens 101 | /src/types -> for Types 102 | ``` 103 | 104 | if you find these useful don't forget to give it a star ⭐ and share it to your friends ❤️ 105 | 106 | Reach me on [twitter](https://twitter.com/kikiding/) 107 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "template-typescript-bottom-tabs-supabase-auth-flow", 4 | "slug": "template-typescript-bottom-tabs-supabase-auth-flow", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "splash": { 9 | "image": "./assets/splash.png", 10 | "resizeMode": "contain", 11 | "backgroundColor": "#ffffff" 12 | }, 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "supportsTablet": true 21 | }, 22 | "android": { 23 | "adaptiveIcon": { 24 | "foregroundImage": "./assets/adaptive-icon.png", 25 | "backgroundColor": "#FFFFFF" 26 | } 27 | }, 28 | "web": { 29 | "favicon": "./assets/favicon.png" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/adaptive-icon.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/favicon.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/icon.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/images/favicon.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/images/forget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/images/forget.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/images/icon.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/images/login.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/images/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/images/register.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/images/splash.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingki/react-native-expo-template/8c2ec7b27005f6bfea818b29c0614159f638f96e/template-typescript-bottom-tabs-supabase-auth-flow/assets/splash.png -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "@expo/vector-icons": "^12.0.0", 12 | "@react-native-async-storage/async-storage": "~1.15.0", 13 | "@react-navigation/bottom-tabs": "^6.0.9", 14 | "@react-navigation/native": "^6.0.6", 15 | "@react-navigation/native-stack": "^6.2.5", 16 | "@supabase/supabase-js": "^1.29.1", 17 | "expo": "~44.0.0", 18 | "expo-asset": "~8.4.5", 19 | "expo-font": "~10.0.4", 20 | "expo-status-bar": "~1.2.0", 21 | "firebase": "^9.6.1", 22 | "react": "17.0.1", 23 | "react-dom": "17.0.1", 24 | "react-native": "0.64.3", 25 | "react-native-rapi-ui": "^0.2.1", 26 | "react-native-safe-area-context": "3.3.2", 27 | "react-native-screens": "~3.10.1", 28 | "react-native-web": "0.17.1" 29 | }, 30 | "devDependencies": { 31 | "@babel/core": "^7.12.9", 32 | "@types/react": "~17.0.21", 33 | "@types/react-native": "~0.64.12", 34 | "typescript": "~4.3.5" 35 | }, 36 | "private": true 37 | } 38 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/components/utils/TabBarIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { themeColor, useTheme } from "react-native-rapi-ui"; 3 | import { Ionicons } from "@expo/vector-icons"; 4 | 5 | export default ({ icon, focused }: { icon: any; focused: boolean }) => { 6 | const { isDarkmode } = useTheme(); 7 | return ( 8 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/components/utils/TabBarText.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Text, themeColor, useTheme } from "react-native-rapi-ui"; 3 | export default ({ title, focused }: { title: string; focused: boolean }) => { 4 | const { isDarkmode } = useTheme(); 5 | return ( 6 | 18 | {title} 19 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/initSupabase.ts: -------------------------------------------------------------------------------- 1 | import AsyncStorage from "@react-native-async-storage/async-storage"; 2 | import { createClient } from "@supabase/supabase-js"; 3 | 4 | // Better put your these secret keys in .env file 5 | export const supabase = createClient("supabaseUrl", "supabaseKey", { 6 | localStorage: AsyncStorage as any, 7 | detectSessionInUrl: false // Prevents Supabase from evaluating window.location.href, breaking mobile 8 | }); 9 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/navigation/AuthStack.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { createNativeStackNavigator } from "@react-navigation/native-stack"; 3 | 4 | import Login from "../screens/auth/Login"; 5 | import Register from "../screens/auth/Register"; 6 | import ForgetPassword from "../screens/auth/ForgetPassword"; 7 | 8 | const AuthStack = createNativeStackNavigator(); 9 | const Auth = () => { 10 | return ( 11 | 16 | 17 | 18 | 19 | 20 | ); 21 | }; 22 | 23 | export default Auth; 24 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/navigation/MainStack.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { createNativeStackNavigator } from "@react-navigation/native-stack"; 3 | 4 | import SecondScreen from "../screens/SecondScreen"; 5 | import MainTabs from "./MainTabs"; 6 | 7 | const MainStack = createNativeStackNavigator(); 8 | const Main = () => { 9 | return ( 10 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default Main; 22 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/navigation/MainTabs.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; 3 | 4 | import { themeColor, useTheme } from "react-native-rapi-ui"; 5 | import TabBarIcon from "../components/utils/TabBarIcon"; 6 | import TabBarText from "../components/utils/TabBarText"; 7 | 8 | import Home from "../screens/Home"; 9 | import About from "../screens/About"; 10 | import Profile from "../screens/Profile"; 11 | 12 | const Tabs = createBottomTabNavigator(); 13 | const MainTabs = () => { 14 | const { isDarkmode } = useTheme(); 15 | return ( 16 | 25 | {/* these icons using Ionicons */} 26 | ( 31 | 32 | ), 33 | tabBarIcon: ({ focused }) => ( 34 | 35 | ), 36 | }} 37 | /> 38 | ( 43 | 44 | ), 45 | tabBarIcon: ({ focused }) => ( 46 | 47 | ), 48 | }} 49 | /> 50 | ( 55 | 56 | ), 57 | tabBarIcon: ({ focused }) => ( 58 | 59 | ), 60 | }} 61 | /> 62 | 63 | ); 64 | }; 65 | 66 | export default MainTabs; 67 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/navigation/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { AuthContext } from '../provider/AuthProvider'; 3 | 4 | import { NavigationContainer } from '@react-navigation/native'; 5 | 6 | import Main from './MainStack'; 7 | import Auth from './AuthStack'; 8 | import Loading from '../screens/utils/Loading'; 9 | 10 | export default () => { 11 | const auth = useContext(AuthContext); 12 | const user = auth.user; 13 | return ( 14 | 15 | {user == null && } 16 | {user == false && } 17 | {user == true &&
} 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/provider/AuthProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState, useEffect } from 'react'; 2 | import { supabase } from '../initSupabase'; 3 | import { Session } from '@supabase/supabase-js'; 4 | type ContextProps = { 5 | user: null | boolean; 6 | session: Session | null; 7 | }; 8 | 9 | const AuthContext = createContext>({}); 10 | 11 | interface Props { 12 | children: React.ReactNode; 13 | } 14 | 15 | const AuthProvider = (props: Props) => { 16 | // user null = loading 17 | const [user, setUser] = useState(null); 18 | const [session, setSession] = useState(null); 19 | 20 | useEffect(() => { 21 | const session = supabase.auth.session(); 22 | setSession(session); 23 | setUser(session ? true : false); 24 | const { data: authListener } = supabase.auth.onAuthStateChange( 25 | async (event, session) => { 26 | console.log(`Supabase auth event: ${event}`); 27 | setSession(session); 28 | setUser(session ? true : false); 29 | } 30 | ); 31 | return () => { 32 | authListener!.unsubscribe(); 33 | }; 34 | }, [user]); 35 | 36 | return ( 37 | 43 | {props.children} 44 | 45 | ); 46 | }; 47 | 48 | export { AuthContext, AuthProvider }; 49 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/screens/About.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | import { MainStackParamList } from "../types/navigation"; 4 | import { NativeStackScreenProps } from "@react-navigation/native-stack"; 5 | import { Layout, Text } from "react-native-rapi-ui"; 6 | 7 | export default function ({ 8 | navigation, 9 | }: NativeStackScreenProps) { 10 | return ( 11 | 12 | 19 | This is the About tab 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/screens/Home.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View, Linking } from "react-native"; 3 | import { MainStackParamList } from "../types/navigation"; 4 | import { NativeStackScreenProps } from "@react-navigation/native-stack"; 5 | import { supabase } from "../initSupabase"; 6 | import { 7 | Layout, 8 | Button, 9 | Text, 10 | TopNav, 11 | Section, 12 | SectionContent, 13 | useTheme, 14 | themeColor, 15 | } from "react-native-rapi-ui"; 16 | import { Ionicons } from "@expo/vector-icons"; 17 | 18 | export default function ({ 19 | navigation, 20 | }: NativeStackScreenProps) { 21 | const { isDarkmode, setTheme } = useTheme(); 22 | return ( 23 | 24 | 32 | } 33 | rightAction={() => { 34 | if (isDarkmode) { 35 | setTheme("light"); 36 | } else { 37 | setTheme("dark"); 38 | } 39 | }} 40 | /> 41 | 48 |
49 | 50 | 51 | These UI components provided by Rapi UI 52 | 53 |
86 |
87 |
88 | ); 89 | } 90 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/screens/Profile.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | import { MainStackParamList } from "../types/navigation"; 4 | import { NativeStackScreenProps } from "@react-navigation/native-stack"; 5 | import { Layout, Text } from "react-native-rapi-ui"; 6 | 7 | export default function ({ 8 | navigation, 9 | }: NativeStackScreenProps) { 10 | return ( 11 | 12 | 19 | This is the Profile tab 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/screens/SecondScreen.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | import { MainStackParamList } from "../types/navigation"; 4 | import { NativeStackScreenProps } from "@react-navigation/native-stack"; 5 | import { 6 | Layout, 7 | TopNav, 8 | Text, 9 | themeColor, 10 | useTheme, 11 | } from "react-native-rapi-ui"; 12 | import { Ionicons } from "@expo/vector-icons"; 13 | 14 | export default function ({ 15 | navigation, 16 | }: NativeStackScreenProps) { 17 | const { isDarkmode, setTheme } = useTheme(); 18 | return ( 19 | 20 | 28 | } 29 | leftAction={() => navigation.goBack()} 30 | rightContent={ 31 | 36 | } 37 | rightAction={() => { 38 | if (isDarkmode) { 39 | setTheme("light"); 40 | } else { 41 | setTheme("dark"); 42 | } 43 | }} 44 | /> 45 | 52 | {/* This text using ubuntu font */} 53 | This is the second screen 54 | 55 | 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /template-typescript-bottom-tabs-supabase-auth-flow/src/screens/auth/ForgetPassword.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { StatusBar } from "expo-status-bar"; 3 | import { 4 | ScrollView, 5 | TouchableOpacity, 6 | View, 7 | KeyboardAvoidingView, 8 | Image, 9 | } from "react-native"; 10 | import { supabase } from "../../initSupabase"; 11 | import { AuthStackParamList } from "../../types/navigation"; 12 | import { NativeStackScreenProps } from "@react-navigation/native-stack"; 13 | import { 14 | Layout, 15 | Text, 16 | TextInput, 17 | Button, 18 | useTheme, 19 | themeColor, 20 | } from "react-native-rapi-ui"; 21 | 22 | export default function ({ 23 | navigation, 24 | }: NativeStackScreenProps) { 25 | const { isDarkmode, setTheme } = useTheme(); 26 | const [email, setEmail] = useState(""); 27 | const [loading, setLoading] = useState(false); 28 | 29 | async function forget() { 30 | setLoading(true); 31 | const { data, error } = await supabase.auth.api.resetPasswordForEmail( 32 | email 33 | ); 34 | if (!error) { 35 | setLoading(false); 36 | alert("Check your email to reset your password!"); 37 | } 38 | if (error) { 39 | setLoading(false); 40 | alert(error.message); 41 | } 42 | } 43 | return ( 44 | 45 | 46 | 51 | 59 | 67 | 68 | 76 | 84 | Forget Password 85 | 86 | Email 87 | setEmail(text)} 96 | /> 97 |