├── .watmanconfig ├── apps └── borg │ ├── .watchmanconifg │ ├── hooks │ ├── useColorScheme.ts │ ├── useColorScheme.web.ts │ └── useThemeColor.ts │ ├── assets │ ├── images │ │ ├── icon.png │ │ ├── splash.png │ │ ├── favicon.png │ │ ├── react-logo.png │ │ ├── adaptive-icon.png │ │ ├── react-logo@2x.png │ │ ├── react-logo@3x.png │ │ └── partial-react-logo.png │ └── fonts │ │ └── SpaceMono-Regular.ttf │ ├── tsconfig.json │ ├── components │ ├── __tests__ │ │ ├── ThemedText-test.tsx │ │ └── __snapshots__ │ │ │ └── ThemedText-test.tsx.snap │ ├── navigation │ │ └── TabBarIcon.tsx │ ├── ThemedView.tsx │ ├── ExternalLink.tsx │ ├── HelloWave.tsx │ ├── Collapsible.tsx │ ├── ThemedText.tsx │ └── ParallaxScrollView.tsx │ ├── .gitignore │ ├── metro.config.js │ ├── constants │ └── Colors.ts │ ├── app │ ├── +not-found.tsx │ ├── _layout.tsx │ ├── (tabs) │ │ ├── _layout.tsx │ │ ├── index.tsx │ │ └── explore.tsx │ └── +html.tsx │ ├── app.json │ ├── package.json │ ├── README.md │ └── scripts │ └── reset-project.js ├── README.md ├── .gitignore └── package.json /.watmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "prefer_split_fsevents_watcher": true 3 | } 4 | -------------------------------------------------------------------------------- /apps/borg/.watchmanconifg: -------------------------------------------------------------------------------- 1 | { 2 | "prefer_split_fsevents_watcher": true 3 | } 4 | -------------------------------------------------------------------------------- /apps/borg/hooks/useColorScheme.ts: -------------------------------------------------------------------------------- 1 | export { useColorScheme } from 'react-native'; 2 | -------------------------------------------------------------------------------- /apps/borg/assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/icon.png -------------------------------------------------------------------------------- /apps/borg/assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/splash.png -------------------------------------------------------------------------------- /apps/borg/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/favicon.png -------------------------------------------------------------------------------- /apps/borg/assets/images/react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/react-logo.png -------------------------------------------------------------------------------- /apps/borg/assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /apps/borg/assets/images/react-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/react-logo@2x.png -------------------------------------------------------------------------------- /apps/borg/assets/images/react-logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/react-logo@3x.png -------------------------------------------------------------------------------- /apps/borg/assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /apps/borg/assets/images/partial-react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sync/borg/main/apps/borg/assets/images/partial-react-logo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome 👋 2 | 3 | ## Get started 4 | 5 | 1. Install dependencies 6 | 7 | ```bash 8 | yarn install 9 | ``` 10 | 11 | 2. Prebuild 12 | 13 | ```bash 14 | yarn prebuild 15 | ``` 16 | 17 | 3. Start the android app 18 | 19 | ```bash 20 | yarn android 21 | ``` 22 | -------------------------------------------------------------------------------- /apps/borg/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true, 5 | "paths": { 6 | "@/*": [ 7 | "./*" 8 | ] 9 | } 10 | }, 11 | "include": [ 12 | "**/*.ts", 13 | "**/*.tsx", 14 | ".expo/types/**/*.ts", 15 | "expo-env.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | 16 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb 17 | # The following patterns were generated by expo-cli 18 | 19 | expo-env.d.ts 20 | # @end expo-cli -------------------------------------------------------------------------------- /apps/borg/components/__tests__/ThemedText-test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | 4 | import { ThemedText } from '../ThemedText'; 5 | 6 | it(`renders correctly`, () => { 7 | const tree = renderer.create(Snapshot test!).toJSON(); 8 | 9 | expect(tree).toMatchSnapshot(); 10 | }); 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "borg-mono", 3 | "private": true, 4 | "workspaces": [ 5 | "apps/*", 6 | "packages/*" 7 | ], 8 | "scripts": { 9 | "prebuild": "yarn workspace borg prebuild", 10 | "start": "yarn workspace borg start", 11 | "ios": "yarn workspace borg ios", 12 | "android": "yarn workspace borg android" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /apps/borg/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | 16 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb 17 | # The following patterns were generated by expo-cli 18 | 19 | expo-env.d.ts 20 | # @end expo-cli 21 | 22 | ios 23 | android 24 | -------------------------------------------------------------------------------- /apps/borg/components/__tests__/__snapshots__/ThemedText-test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`renders correctly 1`] = ` 4 | 22 | Snapshot test! 23 | 24 | `; 25 | -------------------------------------------------------------------------------- /apps/borg/components/navigation/TabBarIcon.tsx: -------------------------------------------------------------------------------- 1 | // You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/ 2 | 3 | import Ionicons from '@expo/vector-icons/Ionicons'; 4 | import { type IconProps } from '@expo/vector-icons/build/createIconSet'; 5 | import { type ComponentProps } from 'react'; 6 | 7 | export function TabBarIcon({ style, ...rest }: IconProps['name']>) { 8 | return ; 9 | } 10 | -------------------------------------------------------------------------------- /apps/borg/hooks/useColorScheme.web.ts: -------------------------------------------------------------------------------- 1 | // NOTE: The default React Native styling doesn't support server rendering. 2 | // Server rendered styles should not change between the first render of the HTML 3 | // and the first render on the client. Typically, web developers will use CSS media queries 4 | // to render different styles on the client and server, these aren't directly supported in React Native 5 | // but can be achieved using a styling library like Nativewind. 6 | export function useColorScheme() { 7 | return 'light'; 8 | } 9 | -------------------------------------------------------------------------------- /apps/borg/components/ThemedView.tsx: -------------------------------------------------------------------------------- 1 | import { View, type ViewProps } from 'react-native'; 2 | 3 | import { useThemeColor } from '@/hooks/useThemeColor'; 4 | 5 | export type ThemedViewProps = ViewProps & { 6 | lightColor?: string; 7 | darkColor?: string; 8 | }; 9 | 10 | export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) { 11 | const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background'); 12 | 13 | return ; 14 | } 15 | -------------------------------------------------------------------------------- /apps/borg/hooks/useThemeColor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about light and dark modes: 3 | * https://docs.expo.dev/guides/color-schemes/ 4 | */ 5 | 6 | import { useColorScheme } from 'react-native'; 7 | 8 | import { Colors } from '@/constants/Colors'; 9 | 10 | export function useThemeColor( 11 | props: { light?: string; dark?: string }, 12 | colorName: keyof typeof Colors.light & keyof typeof Colors.dark 13 | ) { 14 | const theme = useColorScheme() ?? 'light'; 15 | const colorFromProps = props[theme]; 16 | 17 | if (colorFromProps) { 18 | return colorFromProps; 19 | } else { 20 | return Colors[theme][colorName]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /apps/borg/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig } = require("expo/metro-config"); 2 | const path = require("path"); 3 | 4 | // Find the project and workspace directories 5 | const projectRoot = __dirname; 6 | // This can be replaced with `find-yarn-workspace-root` 7 | const monorepoRoot = path.resolve(projectRoot, "../.."); 8 | 9 | const config = getDefaultConfig(projectRoot); 10 | 11 | // 1. Watch all files within the monorepo 12 | config.watchFolders = [monorepoRoot]; 13 | // 2. Let Metro know where to resolve packages and in what order 14 | config.resolver.nodeModulesPaths = [ 15 | path.resolve(projectRoot, "node_modules"), 16 | path.resolve(monorepoRoot, "node_modules"), 17 | ]; 18 | 19 | module.exports = config; 20 | -------------------------------------------------------------------------------- /apps/borg/components/ExternalLink.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'expo-router'; 2 | import { openBrowserAsync } from 'expo-web-browser'; 3 | import { type ComponentProps } from 'react'; 4 | import { Platform } from 'react-native'; 5 | 6 | type Props = Omit, 'href'> & { href: string }; 7 | 8 | export function ExternalLink({ href, ...rest }: Props) { 9 | return ( 10 | { 15 | if (Platform.OS !== 'web') { 16 | // Prevent the default behavior of linking to the default browser on native. 17 | event.preventDefault(); 18 | // Open the link in an in-app browser. 19 | await openBrowserAsync(href); 20 | } 21 | }} 22 | /> 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /apps/borg/constants/Colors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Below are the colors that are used in the app. The colors are defined in the light and dark mode. 3 | * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc. 4 | */ 5 | 6 | const tintColorLight = '#0a7ea4'; 7 | const tintColorDark = '#fff'; 8 | 9 | export const Colors = { 10 | light: { 11 | text: '#11181C', 12 | background: '#fff', 13 | tint: tintColorLight, 14 | icon: '#687076', 15 | tabIconDefault: '#687076', 16 | tabIconSelected: tintColorLight, 17 | }, 18 | dark: { 19 | text: '#ECEDEE', 20 | background: '#151718', 21 | tint: tintColorDark, 22 | icon: '#9BA1A6', 23 | tabIconDefault: '#9BA1A6', 24 | tabIconSelected: tintColorDark, 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /apps/borg/app/+not-found.tsx: -------------------------------------------------------------------------------- 1 | import { Link, Stack } from 'expo-router'; 2 | import { StyleSheet } from 'react-native'; 3 | 4 | import { ThemedText } from '@/components/ThemedText'; 5 | import { ThemedView } from '@/components/ThemedView'; 6 | 7 | export default function NotFoundScreen() { 8 | return ( 9 | <> 10 | 11 | 12 | This screen doesn't exist. 13 | 14 | Go to home screen! 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | const styles = StyleSheet.create({ 22 | container: { 23 | flex: 1, 24 | alignItems: 'center', 25 | justifyContent: 'center', 26 | padding: 20, 27 | }, 28 | link: { 29 | marginTop: 15, 30 | paddingVertical: 15, 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /apps/borg/components/HelloWave.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import Animated, { 3 | useSharedValue, 4 | useAnimatedStyle, 5 | withTiming, 6 | withRepeat, 7 | withSequence, 8 | } from 'react-native-reanimated'; 9 | 10 | import { ThemedText } from '@/components/ThemedText'; 11 | 12 | export function HelloWave() { 13 | const rotationAnimation = useSharedValue(0); 14 | 15 | rotationAnimation.value = withRepeat( 16 | withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })), 17 | 4 // Run the animation 4 times 18 | ); 19 | 20 | const animatedStyle = useAnimatedStyle(() => ({ 21 | transform: [{ rotate: `${rotationAnimation.value}deg` }], 22 | })); 23 | 24 | return ( 25 | 26 | 👋 27 | 28 | ); 29 | } 30 | 31 | const styles = StyleSheet.create({ 32 | text: { 33 | fontSize: 28, 34 | lineHeight: 32, 35 | marginTop: -6, 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /apps/borg/app/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; 2 | import { useFonts } from 'expo-font'; 3 | import { Stack } from 'expo-router'; 4 | import * as SplashScreen from 'expo-splash-screen'; 5 | import { useEffect } from 'react'; 6 | 7 | import { useColorScheme } from '@/hooks/useColorScheme'; 8 | 9 | // Prevent the splash screen from auto-hiding before asset loading is complete. 10 | SplashScreen.preventAutoHideAsync(); 11 | 12 | export default function RootLayout() { 13 | const colorScheme = useColorScheme(); 14 | const [loaded] = useFonts({ 15 | SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), 16 | }); 17 | 18 | useEffect(() => { 19 | if (loaded) { 20 | SplashScreen.hideAsync(); 21 | } 22 | }, [loaded]); 23 | 24 | if (!loaded) { 25 | return null; 26 | } 27 | 28 | return ( 29 | 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /apps/borg/app/(tabs)/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { Tabs } from 'expo-router'; 2 | import React from 'react'; 3 | 4 | import { TabBarIcon } from '@/components/navigation/TabBarIcon'; 5 | import { Colors } from '@/constants/Colors'; 6 | import { useColorScheme } from '@/hooks/useColorScheme'; 7 | 8 | export default function TabLayout() { 9 | const colorScheme = useColorScheme(); 10 | 11 | return ( 12 | 17 | ( 22 | 23 | ), 24 | }} 25 | /> 26 | ( 31 | 32 | ), 33 | }} 34 | /> 35 | 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /apps/borg/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "borg", 4 | "slug": "borg", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/images/icon.png", 8 | "scheme": "myapp", 9 | "userInterfaceStyle": "automatic", 10 | "splash": { 11 | "image": "./assets/images/splash.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "ios": { 16 | "supportsTablet": true, 17 | "bundleIdentifier": "com.anthonymittaz.borg" 18 | }, 19 | "android": { 20 | "adaptiveIcon": { 21 | "foregroundImage": "./assets/images/adaptive-icon.png", 22 | "backgroundColor": "#ffffff" 23 | }, 24 | "package": "com.anthonymittaz.borg" 25 | }, 26 | "web": { 27 | "bundler": "metro", 28 | "output": "static", 29 | "favicon": "./assets/images/favicon.png" 30 | }, 31 | "plugins": [ 32 | "expo-router", 33 | [ 34 | "expo-build-properties", 35 | { 36 | "ios": { 37 | "newArchEnabled": true 38 | }, 39 | "android": { 40 | "newArchEnabled": true 41 | } 42 | } 43 | ] 44 | ], 45 | "experiments": { 46 | "typedRoutes": true 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /apps/borg/components/Collapsible.tsx: -------------------------------------------------------------------------------- 1 | import Ionicons from '@expo/vector-icons/Ionicons'; 2 | import { PropsWithChildren, useState } from 'react'; 3 | import { StyleSheet, TouchableOpacity, useColorScheme } from 'react-native'; 4 | 5 | import { ThemedText } from '@/components/ThemedText'; 6 | import { ThemedView } from '@/components/ThemedView'; 7 | import { Colors } from '@/constants/Colors'; 8 | 9 | export function Collapsible({ children, title }: PropsWithChildren & { title: string }) { 10 | const [isOpen, setIsOpen] = useState(false); 11 | const theme = useColorScheme() ?? 'light'; 12 | 13 | return ( 14 | 15 | setIsOpen((value) => !value)} 18 | activeOpacity={0.8}> 19 | 24 | {title} 25 | 26 | {isOpen && {children}} 27 | 28 | ); 29 | } 30 | 31 | const styles = StyleSheet.create({ 32 | heading: { 33 | flexDirection: 'row', 34 | alignItems: 'center', 35 | gap: 6, 36 | }, 37 | content: { 38 | marginTop: 6, 39 | marginLeft: 24, 40 | }, 41 | }); 42 | -------------------------------------------------------------------------------- /apps/borg/components/ThemedText.tsx: -------------------------------------------------------------------------------- 1 | import { Text, type TextProps, StyleSheet } from 'react-native'; 2 | 3 | import { useThemeColor } from '@/hooks/useThemeColor'; 4 | 5 | export type ThemedTextProps = TextProps & { 6 | lightColor?: string; 7 | darkColor?: string; 8 | type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link'; 9 | }; 10 | 11 | export function ThemedText({ 12 | style, 13 | lightColor, 14 | darkColor, 15 | type = 'default', 16 | ...rest 17 | }: ThemedTextProps) { 18 | const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text'); 19 | 20 | return ( 21 | 33 | ); 34 | } 35 | 36 | const styles = StyleSheet.create({ 37 | default: { 38 | fontSize: 16, 39 | lineHeight: 24, 40 | }, 41 | defaultSemiBold: { 42 | fontSize: 16, 43 | lineHeight: 24, 44 | fontWeight: '600', 45 | }, 46 | title: { 47 | fontSize: 32, 48 | fontWeight: 'bold', 49 | lineHeight: 32, 50 | }, 51 | subtitle: { 52 | fontSize: 20, 53 | fontWeight: 'bold', 54 | }, 55 | link: { 56 | lineHeight: 30, 57 | fontSize: 16, 58 | color: '#0a7ea4', 59 | }, 60 | }); 61 | -------------------------------------------------------------------------------- /apps/borg/app/+html.tsx: -------------------------------------------------------------------------------- 1 | import { ScrollViewStyleReset } from 'expo-router/html'; 2 | import { type PropsWithChildren } from 'react'; 3 | 4 | /** 5 | * This file is web-only and used to configure the root HTML for every web page during static rendering. 6 | * The contents of this function only run in Node.js environments and do not have access to the DOM or browser APIs. 7 | */ 8 | export default function Root({ children }: PropsWithChildren) { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | {/* 17 | Disable body scrolling on web. This makes ScrollView components work closer to how they do on native. 18 | However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line. 19 | */} 20 | 21 | 22 | {/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */} 23 |