├── .github └── workflows │ ├── deploy_frontend.yml │ ├── deploy_k8s_orchestrator.yml │ ├── deploy_primary_backend.yml │ ├── deploy_worker.yml │ └── deploy_ws_relayer.yml ├── .gitignore ├── expo-base-app ├── app.json ├── app │ ├── (tabs) │ │ ├── _layout.tsx │ │ ├── explore.tsx │ │ └── index.tsx │ ├── +not-found.tsx │ └── _layout.tsx ├── assets │ ├── fonts │ │ └── SpaceMono-Regular.ttf │ └── images │ │ ├── adaptive-icon.png │ │ ├── favicon.png │ │ ├── icon.png │ │ ├── partial-react-logo.png │ │ ├── react-logo.png │ │ ├── react-logo@2x.png │ │ ├── react-logo@3x.png │ │ └── splash-icon.png ├── components │ ├── Collapsible.tsx │ ├── ExternalLink.tsx │ ├── HapticTab.tsx │ ├── HelloWave.tsx │ ├── ParallaxScrollView.tsx │ ├── ThemedText.tsx │ ├── ThemedView.tsx │ ├── __tests__ │ │ ├── ThemedText-test.tsx │ │ └── __snapshots__ │ │ │ └── ThemedText-test.tsx.snap │ └── ui │ │ ├── IconSymbol.ios.tsx │ │ ├── IconSymbol.tsx │ │ ├── TabBarBackground.ios.tsx │ │ └── TabBarBackground.tsx ├── constants │ └── Colors.ts ├── hooks │ ├── useColorScheme.ts │ ├── useColorScheme.web.ts │ └── useThemeColor.ts ├── package.json └── tsconfig.json ├── ext ├── .gitignore ├── CHANGELOG.md ├── README.md ├── bolty-listener-0.0.1.vsix ├── eslint.config.mjs ├── index.js ├── package-lock.json ├── package.json ├── src │ ├── extension.ts │ └── test │ │ └── extension.test.ts ├── tsconfig.json └── vsc-extension-quickstart.md ├── framework-serializer ├── .gitignore ├── README.md ├── bun.lock ├── index.ts ├── package.json └── tsconfig.json ├── mobile-magic ├── .gitignore ├── .npmrc ├── README.md ├── apps │ ├── frontend │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app │ │ │ ├── favicon.ico │ │ │ ├── globals.css │ │ │ ├── layout.tsx │ │ │ ├── page.tsx │ │ │ ├── project │ │ │ │ └── [projectId] │ │ │ │ │ ├── Project.tsx │ │ │ │ │ └── page.tsx │ │ │ └── provider.tsx │ │ ├── components.json │ │ ├── components │ │ │ ├── Appbar.tsx │ │ │ ├── Header.tsx │ │ │ ├── PreviewIframe.tsx │ │ │ ├── ProjectWithInitRequest.tsx │ │ │ ├── ProjectsDrawer.tsx │ │ │ ├── Prompt.tsx │ │ │ ├── SideInfo.tsx │ │ │ ├── TemplateButtons.tsx │ │ │ ├── ToggleTheme.tsx │ │ │ ├── app-sidebar.tsx │ │ │ ├── hero.tsx │ │ │ ├── theme-button.tsx │ │ │ ├── theme-provider.tsx │ │ │ └── ui │ │ │ │ ├── alert-dialog.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── drawer.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── label.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── sheet.tsx │ │ │ │ ├── sidebar.tsx │ │ │ │ ├── skeleton.tsx │ │ │ │ ├── sonner.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── textarea.tsx │ │ │ │ └── tooltip.tsx │ │ ├── config.ts │ │ ├── eslint.config.mjs │ │ ├── hooks │ │ │ ├── use-mobile.ts │ │ │ ├── useDebounce.ts │ │ │ ├── useProject.ts │ │ │ └── usePrompts.tsx │ │ ├── lib │ │ │ ├── animation-variants.ts │ │ │ ├── constants.ts │ │ │ └── utils.ts │ │ ├── middleware.ts │ │ ├── next.config.ts │ │ ├── package.json │ │ ├── postcss.config.mjs │ │ ├── public │ │ │ ├── file.svg │ │ │ ├── globe.svg │ │ │ ├── logo.svg │ │ │ ├── next.svg │ │ │ ├── vercel.svg │ │ │ └── window.svg │ │ ├── tsconfig.json │ │ └── utils │ │ │ └── formatDate.ts │ ├── k8s-orchestrator │ │ ├── .gitignore │ │ ├── README.md │ │ ├── config.ts │ │ ├── index.ts │ │ ├── names.ts │ │ ├── package.json │ │ ├── redis.ts │ │ └── tsconfig.json │ ├── primary-backend │ │ ├── .env.example │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.ts │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── types.d.ts │ ├── worker-orchestrator │ │ ├── .env.example │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ ├── worker │ │ ├── .env.example │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.ts │ │ ├── os.ts │ │ ├── package.json │ │ ├── parser.ts │ │ ├── systemPrompt.tsx │ │ ├── tsconfig.json │ │ ├── types.d.ts │ │ ├── worker.test.ts │ │ └── ws.ts │ └── ws-relayer │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json ├── bun.lock ├── docker-compose.yml ├── docker │ ├── Dockerfile.code-server │ ├── Dockerfile.frontend │ ├── Dockerfile.frontend.prod │ ├── Dockerfile.k8s-orchestrator │ ├── Dockerfile.primary-backend │ ├── Dockerfile.worker │ └── Dockerfile.ws-relayer ├── package.json ├── packages │ ├── common │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.ts │ │ ├── middleware.ts │ │ ├── package.json │ │ ├── tsconfig.json │ │ ├── types.d.ts │ │ └── types.ts │ ├── db │ │ ├── .env.example │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.ts │ │ ├── package.json │ │ ├── prisma │ │ │ ├── migrations │ │ │ │ ├── 20250227175716_init │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250227180410_added_prompt │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250227180658_added_user_project_relatiobn │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250228074904_cd │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250301085409_added_actions │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250301085440_added_content │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250307191146_init │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250307201247_add_typ │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250307201550_ │ │ │ │ │ └── migration.sql │ │ │ │ ├── 20250309212901_added_react │ │ │ │ │ └── migration.sql │ │ │ │ └── migration_lock.toml │ │ │ └── schema.prisma │ │ └── tsconfig.json │ ├── eslint-config │ │ ├── README.md │ │ ├── base.js │ │ ├── next.js │ │ ├── package.json │ │ └── react-internal.js │ ├── typescript-config │ │ ├── base.json │ │ ├── nextjs.json │ │ ├── package.json │ │ └── react-library.json │ └── ui │ │ ├── eslint.config.mjs │ │ ├── package.json │ │ ├── src │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── code.tsx │ │ ├── info-banner.tsx │ │ └── particles.tsx │ │ ├── tsconfig.json │ │ └── turbo │ │ └── generators │ │ ├── config.ts │ │ └── templates │ │ └── component.hbs └── turbo.json ├── nextjs-base-app ├── README.md ├── app │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── eslint.config.mjs ├── next-env.d.ts ├── next.config.ts ├── package.json ├── postcss.config.mjs ├── public │ ├── file.svg │ ├── globe.svg │ ├── next.svg │ ├── vercel.svg │ └── window.svg └── tsconfig.json ├── ops ├── .gitignore ├── Caddyfile ├── app │ ├── frontend │ │ ├── .gitignore │ │ ├── deployment.yml │ │ └── service.yml │ ├── k8s-orchestrator │ │ ├── manifest.yml │ │ └── service_account.yml │ └── primary-backend │ │ ├── .gitignore │ │ ├── deployment.yml │ │ └── service.yml ├── caddy.yml ├── deployment.yml ├── monitoring │ ├── grafana-values.yaml │ ├── primary-backend-servicemonitor.yaml │ ├── prometheus-values.yaml │ └── script.sh ├── pod.yml ├── reset.sh └── script.sh └── react-base-app ├── .gitignore ├── components.json ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── public └── vite.svg ├── src ├── App.css ├── App.tsx ├── assets │ └── react.svg ├── components │ └── ui │ │ └── button.tsx ├── index.css ├── lib │ └── utils.ts ├── main.tsx └── vite-env.d.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.github/workflows/deploy_frontend.yml: -------------------------------------------------------------------------------- 1 | name: Docker Publish Frontend 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Login to Docker Hub 15 | uses: docker/login-action@v3 16 | with: 17 | username: ${{ secrets.DOCKERHUB_USERNAME }} 18 | password: ${{ secrets.DOCKERHUB_TOKEN }} 19 | - name: Build and push frontend 20 | uses: docker/build-push-action@v5 21 | with: 22 | context: ./mobile-magic 23 | file: ./mobile-magic/docker/Dockerfile.frontend.prod 24 | push: true 25 | tags: 100xdevs/antidevs-frontend:${{ github.sha }} 26 | build-args: | 27 | NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=${{ secrets.CLERK_PUBLISHABLE_KEY }} 28 | -------------------------------------------------------------------------------- /.github/workflows/deploy_k8s_orchestrator.yml: -------------------------------------------------------------------------------- 1 | name: Docker Orchestrator 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Login to Docker Hub 15 | uses: docker/login-action@v3 16 | with: 17 | username: ${{ secrets.DOCKERHUB_USERNAME }} 18 | password: ${{ secrets.DOCKERHUB_TOKEN }} 19 | - name: Build and push orchestrator 20 | uses: docker/build-push-action@v5 21 | with: 22 | context: ./mobile-magic 23 | file: ./mobile-magic/docker/Dockerfile.k8s-orchestrator 24 | push: true 25 | tags: 100xdevs/antidevs-k8s-orchestrator:${{ github.sha }} 26 | -------------------------------------------------------------------------------- /.github/workflows/deploy_primary_backend.yml: -------------------------------------------------------------------------------- 1 | name: Docker Primary Backend 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Login to Docker Hub 15 | uses: docker/login-action@v3 16 | with: 17 | username: ${{ secrets.DOCKERHUB_USERNAME }} 18 | password: ${{ secrets.DOCKERHUB_TOKEN }} 19 | - name: Build and push primary backend 20 | uses: docker/build-push-action@v5 21 | with: 22 | context: ./mobile-magic 23 | file: ./mobile-magic/docker/Dockerfile.primary-backend 24 | push: true 25 | tags: 100xdevs/antidevs-primary-backend:${{ github.sha }} 26 | -------------------------------------------------------------------------------- /.github/workflows/deploy_worker.yml: -------------------------------------------------------------------------------- 1 | name: Docker Publish Worker 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Login to Docker Hub 15 | uses: docker/login-action@v3 16 | with: 17 | username: ${{ secrets.DOCKERHUB_USERNAME }} 18 | password: ${{ secrets.DOCKERHUB_TOKEN }} 19 | - name: Build and push worker 20 | uses: docker/build-push-action@v5 21 | with: 22 | context: ./mobile-magic 23 | file: ./mobile-magic/docker/Dockerfile.worker 24 | push: true 25 | tags: 100xdevs/antidevs-worker:${{ github.sha }} 26 | -------------------------------------------------------------------------------- /.github/workflows/deploy_ws_relayer.yml: -------------------------------------------------------------------------------- 1 | name: Docker Publish WS Relay 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Login to Docker Hub 15 | uses: docker/login-action@v3 16 | with: 17 | username: ${{ secrets.DOCKERHUB_USERNAME }} 18 | password: ${{ secrets.DOCKERHUB_TOKEN }} 19 | - name: Build and push ws-relayer 20 | uses: docker/build-push-action@v5 21 | with: 22 | context: ./mobile-magic 23 | file: ./mobile-magic/docker/Dockerfile.ws-relayer 24 | push: true 25 | tags: 100xdevs/antidevs-ws-relayer:${{ github.sha }} 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docker-compose.yml 2 | -------------------------------------------------------------------------------- /expo-base-app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "expo-base-app", 4 | "slug": "expo-base-app", 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 | } 42 | -------------------------------------------------------------------------------- /expo-base-app/app/(tabs)/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { Tabs } from 'expo-router'; 2 | import React from 'react'; 3 | import { Platform } from 'react-native'; 4 | 5 | import { HapticTab } from '@/components/HapticTab'; 6 | import { IconSymbol } from '@/components/ui/IconSymbol'; 7 | import TabBarBackground from '@/components/ui/TabBarBackground'; 8 | import { Colors } from '@/constants/Colors'; 9 | import { useColorScheme } from '@/hooks/useColorScheme'; 10 | 11 | export default function TabLayout() { 12 | const colorScheme = useColorScheme(); 13 | 14 | return ( 15 | 29 | , 34 | }} 35 | /> 36 | , 41 | }} 42 | /> 43 | 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /expo-base-app/app/(tabs)/index.tsx: -------------------------------------------------------------------------------- 1 | import { Image, StyleSheet, Platform } from 'react-native'; 2 | 3 | import { HelloWave } from '@/components/HelloWave'; 4 | import ParallaxScrollView from '@/components/ParallaxScrollView'; 5 | import { ThemedText } from '@/components/ThemedText'; 6 | import { ThemedView } from '@/components/ThemedView'; 7 | 8 | export default function HomeScreen() { 9 | return ( 10 | 17 | }> 18 | 19 | Welcome! 20 | 21 | 22 | 23 | Step 1: Try it 24 | 25 | Edit app/(tabs)/index.tsx to see changes. 26 | Press{' '} 27 | 28 | {Platform.select({ 29 | ios: 'cmd + d', 30 | android: 'cmd + m', 31 | web: 'F12' 32 | })} 33 | {' '} 34 | to open developer tools. 35 | 36 | 37 | 38 | Step 2: Explore 39 | 40 | Tap the Explore tab to learn more about what's included in this starter app. 41 | 42 | 43 | 44 | Step 3: Get a fresh start 45 | 46 | When you're ready, run{' '} 47 | npm run reset-project to get a fresh{' '} 48 | app directory. This will move the current{' '} 49 | app to{' '} 50 | app-example. 51 | 52 | 53 | 54 | ); 55 | } 56 | 57 | const styles = StyleSheet.create({ 58 | titleContainer: { 59 | flexDirection: 'row', 60 | alignItems: 'center', 61 | gap: 8, 62 | }, 63 | stepContainer: { 64 | gap: 8, 65 | marginBottom: 8, 66 | }, 67 | reactLogo: { 68 | height: 178, 69 | width: 290, 70 | bottom: 0, 71 | left: 0, 72 | position: 'absolute', 73 | }, 74 | }); 75 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /expo-base-app/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 { StatusBar } from 'expo-status-bar'; 6 | import { useEffect } from 'react'; 7 | import 'react-native-reanimated'; 8 | 9 | import { useColorScheme } from '@/hooks/useColorScheme'; 10 | 11 | // Prevent the splash screen from auto-hiding before asset loading is complete. 12 | SplashScreen.preventAutoHideAsync(); 13 | 14 | export default function RootLayout() { 15 | const colorScheme = useColorScheme(); 16 | const [loaded] = useFonts({ 17 | SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), 18 | }); 19 | 20 | useEffect(() => { 21 | if (loaded) { 22 | SplashScreen.hideAsync(); 23 | } 24 | }, [loaded]); 25 | 26 | if (!loaded) { 27 | return null; 28 | } 29 | 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /expo-base-app/assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /expo-base-app/assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /expo-base-app/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/favicon.png -------------------------------------------------------------------------------- /expo-base-app/assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/icon.png -------------------------------------------------------------------------------- /expo-base-app/assets/images/partial-react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/partial-react-logo.png -------------------------------------------------------------------------------- /expo-base-app/assets/images/react-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/react-logo.png -------------------------------------------------------------------------------- /expo-base-app/assets/images/react-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/react-logo@2x.png -------------------------------------------------------------------------------- /expo-base-app/assets/images/react-logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/react-logo@3x.png -------------------------------------------------------------------------------- /expo-base-app/assets/images/splash-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/expo-base-app/assets/images/splash-icon.png -------------------------------------------------------------------------------- /expo-base-app/components/Collapsible.tsx: -------------------------------------------------------------------------------- 1 | import { PropsWithChildren, useState } from 'react'; 2 | import { StyleSheet, TouchableOpacity } from 'react-native'; 3 | 4 | import { ThemedText } from '@/components/ThemedText'; 5 | import { ThemedView } from '@/components/ThemedView'; 6 | import { IconSymbol } from '@/components/ui/IconSymbol'; 7 | import { Colors } from '@/constants/Colors'; 8 | import { useColorScheme } from '@/hooks/useColorScheme'; 9 | 10 | export function Collapsible({ children, title }: PropsWithChildren & { title: string }) { 11 | const [isOpen, setIsOpen] = useState(false); 12 | const theme = useColorScheme() ?? 'light'; 13 | 14 | return ( 15 | 16 | setIsOpen((value) => !value)} 19 | activeOpacity={0.8}> 20 | 27 | 28 | {title} 29 | 30 | {isOpen && {children}} 31 | 32 | ); 33 | } 34 | 35 | const styles = StyleSheet.create({ 36 | heading: { 37 | flexDirection: 'row', 38 | alignItems: 'center', 39 | gap: 6, 40 | }, 41 | content: { 42 | marginTop: 6, 43 | marginLeft: 24, 44 | }, 45 | }); 46 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /expo-base-app/components/HapticTab.tsx: -------------------------------------------------------------------------------- 1 | import { BottomTabBarButtonProps } from '@react-navigation/bottom-tabs'; 2 | import { PlatformPressable } from '@react-navigation/elements'; 3 | import * as Haptics from 'expo-haptics'; 4 | 5 | export function HapticTab(props: BottomTabBarButtonProps) { 6 | return ( 7 | { 10 | if (process.env.EXPO_OS === 'ios') { 11 | // Add a soft haptic feedback when pressing down on the tabs. 12 | Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); 13 | } 14 | props.onPressIn?.(ev); 15 | }} 16 | /> 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /expo-base-app/components/HelloWave.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import Animated, { 4 | useSharedValue, 5 | useAnimatedStyle, 6 | withTiming, 7 | withRepeat, 8 | withSequence, 9 | } from 'react-native-reanimated'; 10 | 11 | import { ThemedText } from '@/components/ThemedText'; 12 | 13 | export function HelloWave() { 14 | const rotationAnimation = useSharedValue(0); 15 | 16 | useEffect(() => { 17 | rotationAnimation.value = withRepeat( 18 | withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })), 19 | 4 // Run the animation 4 times 20 | ); 21 | }, []); 22 | 23 | const animatedStyle = useAnimatedStyle(() => ({ 24 | transform: [{ rotate: `${rotationAnimation.value}deg` }], 25 | })); 26 | 27 | return ( 28 | 29 | 👋 30 | 31 | ); 32 | } 33 | 34 | const styles = StyleSheet.create({ 35 | text: { 36 | fontSize: 28, 37 | lineHeight: 32, 38 | marginTop: -6, 39 | }, 40 | }); 41 | -------------------------------------------------------------------------------- /expo-base-app/components/ParallaxScrollView.tsx: -------------------------------------------------------------------------------- 1 | import type { PropsWithChildren, ReactElement } from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import Animated, { 4 | interpolate, 5 | useAnimatedRef, 6 | useAnimatedStyle, 7 | useScrollViewOffset, 8 | } from 'react-native-reanimated'; 9 | 10 | import { ThemedView } from '@/components/ThemedView'; 11 | import { useBottomTabOverflow } from '@/components/ui/TabBarBackground'; 12 | import { useColorScheme } from '@/hooks/useColorScheme'; 13 | 14 | const HEADER_HEIGHT = 250; 15 | 16 | type Props = PropsWithChildren<{ 17 | headerImage: ReactElement; 18 | headerBackgroundColor: { dark: string; light: string }; 19 | }>; 20 | 21 | export default function ParallaxScrollView({ 22 | children, 23 | headerImage, 24 | headerBackgroundColor, 25 | }: Props) { 26 | const colorScheme = useColorScheme() ?? 'light'; 27 | const scrollRef = useAnimatedRef(); 28 | const scrollOffset = useScrollViewOffset(scrollRef); 29 | const bottom = useBottomTabOverflow(); 30 | const headerAnimatedStyle = useAnimatedStyle(() => { 31 | return { 32 | transform: [ 33 | { 34 | translateY: interpolate( 35 | scrollOffset.value, 36 | [-HEADER_HEIGHT, 0, HEADER_HEIGHT], 37 | [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75] 38 | ), 39 | }, 40 | { 41 | scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]), 42 | }, 43 | ], 44 | }; 45 | }); 46 | 47 | return ( 48 | 49 | 54 | 60 | {headerImage} 61 | 62 | {children} 63 | 64 | 65 | ); 66 | } 67 | 68 | const styles = StyleSheet.create({ 69 | container: { 70 | flex: 1, 71 | }, 72 | header: { 73 | height: HEADER_HEIGHT, 74 | overflow: 'hidden', 75 | }, 76 | content: { 77 | flex: 1, 78 | padding: 32, 79 | gap: 16, 80 | overflow: 'hidden', 81 | }, 82 | }); 83 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /expo-base-app/components/ui/IconSymbol.ios.tsx: -------------------------------------------------------------------------------- 1 | import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols'; 2 | import { StyleProp, ViewStyle } from 'react-native'; 3 | 4 | export function IconSymbol({ 5 | name, 6 | size = 24, 7 | color, 8 | style, 9 | weight = 'regular', 10 | }: { 11 | name: SymbolViewProps['name']; 12 | size?: number; 13 | color: string; 14 | style?: StyleProp; 15 | weight?: SymbolWeight; 16 | }) { 17 | return ( 18 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /expo-base-app/components/ui/IconSymbol.tsx: -------------------------------------------------------------------------------- 1 | // This file is a fallback for using MaterialIcons on Android and web. 2 | 3 | import MaterialIcons from '@expo/vector-icons/MaterialIcons'; 4 | import { SymbolWeight } from 'expo-symbols'; 5 | import React from 'react'; 6 | import { OpaqueColorValue, StyleProp, ViewStyle } from 'react-native'; 7 | 8 | // Add your SFSymbol to MaterialIcons mappings here. 9 | const MAPPING = { 10 | // See MaterialIcons here: https://icons.expo.fyi 11 | // See SF Symbols in the SF Symbols app on Mac. 12 | 'house.fill': 'home', 13 | 'paperplane.fill': 'send', 14 | 'chevron.left.forwardslash.chevron.right': 'code', 15 | 'chevron.right': 'chevron-right', 16 | } as Partial< 17 | Record< 18 | import('expo-symbols').SymbolViewProps['name'], 19 | React.ComponentProps['name'] 20 | > 21 | >; 22 | 23 | export type IconSymbolName = keyof typeof MAPPING; 24 | 25 | /** 26 | * An icon component that uses native SFSymbols on iOS, and MaterialIcons on Android and web. This ensures a consistent look across platforms, and optimal resource usage. 27 | * 28 | * Icon `name`s are based on SFSymbols and require manual mapping to MaterialIcons. 29 | */ 30 | export function IconSymbol({ 31 | name, 32 | size = 24, 33 | color, 34 | style, 35 | }: { 36 | name: IconSymbolName; 37 | size?: number; 38 | color: string | OpaqueColorValue; 39 | style?: StyleProp; 40 | weight?: SymbolWeight; 41 | }) { 42 | return ; 43 | } 44 | -------------------------------------------------------------------------------- /expo-base-app/components/ui/TabBarBackground.ios.tsx: -------------------------------------------------------------------------------- 1 | import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs'; 2 | import { BlurView } from 'expo-blur'; 3 | import { StyleSheet } from 'react-native'; 4 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 5 | 6 | export default function BlurTabBarBackground() { 7 | return ( 8 | 15 | ); 16 | } 17 | 18 | export function useBottomTabOverflow() { 19 | const tabHeight = useBottomTabBarHeight(); 20 | const { bottom } = useSafeAreaInsets(); 21 | return tabHeight - bottom; 22 | } 23 | -------------------------------------------------------------------------------- /expo-base-app/components/ui/TabBarBackground.tsx: -------------------------------------------------------------------------------- 1 | // This is a shim for web and Android where the tab bar is generally opaque. 2 | export default undefined; 3 | 4 | export function useBottomTabOverflow() { 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /expo-base-app/hooks/useColorScheme.ts: -------------------------------------------------------------------------------- 1 | export { useColorScheme } from 'react-native'; 2 | -------------------------------------------------------------------------------- /expo-base-app/hooks/useColorScheme.web.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import { useColorScheme as useRNColorScheme } from 'react-native'; 3 | 4 | /** 5 | * To support static rendering, this value needs to be re-calculated on the client side for web 6 | */ 7 | export function useColorScheme() { 8 | const [hasHydrated, setHasHydrated] = useState(false); 9 | 10 | useEffect(() => { 11 | setHasHydrated(true); 12 | }, []); 13 | 14 | const colorScheme = useRNColorScheme(); 15 | 16 | if (hasHydrated) { 17 | return colorScheme; 18 | } 19 | 20 | return 'light'; 21 | } 22 | -------------------------------------------------------------------------------- /expo-base-app/hooks/useThemeColor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about light and dark modes: 3 | * https://docs.expo.dev/guides/color-schemes/ 4 | */ 5 | 6 | import { Colors } from '@/constants/Colors'; 7 | import { useColorScheme } from '@/hooks/useColorScheme'; 8 | 9 | export function useThemeColor( 10 | props: { light?: string; dark?: string }, 11 | colorName: keyof typeof Colors.light & keyof typeof Colors.dark 12 | ) { 13 | const theme = useColorScheme() ?? 'light'; 14 | const colorFromProps = props[theme]; 15 | 16 | if (colorFromProps) { 17 | return colorFromProps; 18 | } else { 19 | return Colors[theme][colorName]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /expo-base-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "expo-base-app", 3 | "main": "expo-router/entry", 4 | "version": "1.0.0", 5 | "scripts": { 6 | "start": "expo start", 7 | "reset-project": "node ./scripts/reset-project.js", 8 | "android": "expo start --android", 9 | "ios": "expo start --ios", 10 | "web": "expo start --web", 11 | "test": "jest --watchAll", 12 | "lint": "expo lint", 13 | "dev": "expo start --port 8081" 14 | }, 15 | "jest": { 16 | "preset": "jest-expo" 17 | }, 18 | "dependencies": { 19 | "@expo/vector-icons": "^14.0.2", 20 | "@react-navigation/bottom-tabs": "^7.2.0", 21 | "@react-navigation/native": "^7.0.14", 22 | "expo": "~52.0.37", 23 | "expo-blur": "~14.0.3", 24 | "expo-constants": "~17.0.7", 25 | "expo-font": "~13.0.4", 26 | "expo-haptics": "~14.0.1", 27 | "expo-linking": "~7.0.5", 28 | "expo-router": "~4.0.17", 29 | "expo-splash-screen": "~0.29.22", 30 | "expo-status-bar": "~2.0.1", 31 | "expo-symbols": "~0.2.2", 32 | "expo-system-ui": "~4.0.8", 33 | "expo-web-browser": "~14.0.2", 34 | "react": "18.3.1", 35 | "react-dom": "18.3.1", 36 | "react-native": "0.76.7", 37 | "react-native-gesture-handler": "~2.20.2", 38 | "react-native-reanimated": "~3.16.1", 39 | "react-native-safe-area-context": "4.12.0", 40 | "react-native-screens": "~4.4.0", 41 | "react-native-web": "~0.19.13", 42 | "react-native-webview": "13.12.5" 43 | }, 44 | "devDependencies": { 45 | "@babel/core": "^7.25.2", 46 | "@types/jest": "^29.5.12", 47 | "@types/react": "~18.3.12", 48 | "@types/react-test-renderer": "^18.3.0", 49 | "jest": "^29.2.1", 50 | "jest-expo": "~52.0.4", 51 | "react-test-renderer": "18.3.1", 52 | "typescript": "^5.3.3" 53 | }, 54 | "private": true 55 | } 56 | -------------------------------------------------------------------------------- /expo-base-app/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 | -------------------------------------------------------------------------------- /ext/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | .DS_Store -------------------------------------------------------------------------------- /ext/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "bolty-listener" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [Unreleased] 8 | 9 | - Initial release -------------------------------------------------------------------------------- /ext/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/ext/README.md -------------------------------------------------------------------------------- /ext/bolty-listener-0.0.1.vsix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/ext/bolty-listener-0.0.1.vsix -------------------------------------------------------------------------------- /ext/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import typescriptEslint from "@typescript-eslint/eslint-plugin"; 2 | import tsParser from "@typescript-eslint/parser"; 3 | 4 | export default [{ 5 | files: ["**/*.ts"], 6 | }, { 7 | plugins: { 8 | "@typescript-eslint": typescriptEslint, 9 | }, 10 | 11 | languageOptions: { 12 | parser: tsParser, 13 | ecmaVersion: 2022, 14 | sourceType: "module", 15 | }, 16 | 17 | rules: { 18 | "@typescript-eslint/naming-convention": ["warn", { 19 | selector: "import", 20 | format: ["camelCase", "PascalCase"], 21 | }], 22 | 23 | curly: "warn", 24 | eqeqeq: "warn", 25 | "no-throw-literal": "warn", 26 | semi: "warn", 27 | }, 28 | }]; -------------------------------------------------------------------------------- /ext/index.js: -------------------------------------------------------------------------------- 1 | const {WebSocket} = require("ws") 2 | 3 | const ws = new WebSocket("ws://localhost:8082"); 4 | 5 | ws.onerror = () => {console.log("error")} 6 | 7 | ws.ondata = () => {console.log("message")} 8 | -------------------------------------------------------------------------------- /ext/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bolty-listener", 3 | "displayName": "bolty-listener", 4 | "description": "Listens to changes from an LLM and runs those commands/changes those files", 5 | "version": "0.0.1", 6 | "engines": { 7 | "vscode": "1.96.4" 8 | }, 9 | "categories": [ 10 | "Other" 11 | ], 12 | "activationEvents": ["onStartupFinished", "*"], 13 | "main": "./out/extension.js", 14 | "contributes": { 15 | "commands": [ 16 | { 17 | "command": "bolty-listener.helloWorld", 18 | "title": "Hello World" 19 | } 20 | ] 21 | }, 22 | "scripts": { 23 | "vscode:prepublish": "npm run compile", 24 | "compile": "tsc -p ./", 25 | "watch": "tsc -watch -p ./", 26 | "pretest": "npm run compile && npm run lint", 27 | "lint": "eslint src", 28 | "test": "vscode-test" 29 | }, 30 | "devDependencies": { 31 | "@types/mocha": "^10.0.10", 32 | "@types/node": "20.x", 33 | "@types/vscode": "^1.96.4", 34 | "@typescript-eslint/eslint-plugin": "^8.25.0", 35 | "@typescript-eslint/parser": "^8.25.0", 36 | "@vscode/test-cli": "^0.0.10", 37 | "@vscode/test-electron": "^2.4.1", 38 | "eslint": "^9.21.0", 39 | "typescript": "^5.7.3" 40 | }, 41 | "dependencies": { 42 | "@types/ws": "^8.5.14", 43 | "ws": "^8.18.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ext/src/test/extension.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | 3 | // You can import and use all API from the 'vscode' module 4 | // as well as import your extension to test it 5 | import * as vscode from 'vscode'; 6 | // import * as myExtension from '../../extension'; 7 | 8 | suite('Extension Test Suite', () => { 9 | vscode.window.showInformationMessage('Start all tests.'); 10 | 11 | test('Sample test', () => { 12 | assert.strictEqual(-1, [1, 2, 3].indexOf(5)); 13 | assert.strictEqual(-1, [1, 2, 3].indexOf(0)); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /ext/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "Node16", 4 | "target": "ES2022", 5 | "outDir": "out", 6 | "lib": [ 7 | "ES2022" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": "src", 11 | "strict": true, /* enable all strict type-checking options */ 12 | /* Additional Checks */ 13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /framework-serializer/.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | -------------------------------------------------------------------------------- /framework-serializer/README.md: -------------------------------------------------------------------------------- 1 | # framework-serializer 2 | 3 | To install dependencies: 4 | 5 | ```bash 6 | bun install 7 | ``` 8 | 9 | To run: 10 | 11 | ```bash 12 | bun run index.ts 13 | ``` 14 | 15 | This project was created using `bun init` in bun v1.2.2. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. 16 | -------------------------------------------------------------------------------- /framework-serializer/bun.lock: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1, 3 | "workspaces": { 4 | "": { 5 | "name": "framework-serializer", 6 | "devDependencies": { 7 | "@types/bun": "latest", 8 | }, 9 | "peerDependencies": { 10 | "typescript": "^5.0.0", 11 | }, 12 | }, 13 | }, 14 | "packages": { 15 | "@types/bun": ["@types/bun@1.2.4", "", { "dependencies": { "bun-types": "1.2.4" } }, "sha512-QtuV5OMR8/rdKJs213iwXDpfVvnskPXY/S0ZiFbsTjQZycuqPbMW8Gf/XhLfwE5njW8sxI2WjISURXPlHypMFA=="], 16 | 17 | "@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], 18 | 19 | "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], 20 | 21 | "bun-types": ["bun-types@1.2.4", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-nDPymR207ZZEoWD4AavvEaa/KZe/qlrbMSchqpQwovPZCKc7pwMoENjEtHgMKaAjJhy+x6vfqSBA1QU3bJgs0Q=="], 22 | 23 | "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], 24 | 25 | "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /framework-serializer/index.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs" 2 | import path from "path" 3 | const FOLDER_PATH = "/Users/harkiratsingh/Projects/mobile-magic-parent/base-react-app" 4 | // read through all the files in the folder and print them in tbe bolt artifact format 5 | // It shoudl happen recursively 6 | 7 | const files = fs.readdirSync(FOLDER_PATH) 8 | let artifact = "" 9 | 10 | function serializeFolder(folderPath: string) { 11 | const files = fs.readdirSync(folderPath) 12 | files.forEach(file => { 13 | const filePath = path.join(folderPath, file) 14 | if (fs.statSync(filePath).isDirectory()) { 15 | serializeFolder(filePath) 16 | } else { 17 | if (file.endsWith("package-lock.json") || file.endsWith(".ico") || file.endsWith(".ttf") || file.endsWith(".png") || file.endsWith(".jpg") || file.endsWith(".jpeg") || file.endsWith(".gif") || file.endsWith(".svg") || file.endsWith(".webp")) { 18 | return; 19 | } 20 | 21 | artifact += `` 22 | artifact += fs.readFileSync(filePath, {encoding: "utf-8"}).replaceAll("`", "\\`").replaceAll("$", "\\$") 23 | artifact += `` 24 | } 25 | }) 26 | } 27 | 28 | serializeFolder(FOLDER_PATH) 29 | 30 | console.log(artifact) 31 | -------------------------------------------------------------------------------- /framework-serializer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "framework-serializer", 3 | "module": "index.ts", 4 | "type": "module", 5 | "devDependencies": { 6 | "@types/bun": "latest" 7 | }, 8 | "peerDependencies": { 9 | "typescript": "^5.0.0" 10 | } 11 | } -------------------------------------------------------------------------------- /framework-serializer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // Enable latest features 4 | "lib": ["ESNext", "DOM"], 5 | "target": "ESNext", 6 | "module": "ESNext", 7 | "moduleDetection": "force", 8 | "jsx": "react-jsx", 9 | "allowJs": true, 10 | 11 | // Bundler mode 12 | "moduleResolution": "bundler", 13 | "allowImportingTsExtensions": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | 17 | // Best practices 18 | "strict": true, 19 | "skipLibCheck": true, 20 | "noFallthroughCasesInSwitch": true, 21 | 22 | // Some stricter flags (disabled by default) 23 | "noUnusedLocals": false, 24 | "noUnusedParameters": false, 25 | "noPropertyAccessFromIndexSignature": false 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /mobile-magic/.gitignore: -------------------------------------------------------------------------------- 1 | postgres_data 2 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 3 | 4 | # Dependencies 5 | node_modules 6 | .pnp 7 | .pnp.js 8 | 9 | # Local env files 10 | .env 11 | .env.local 12 | .env.development.local 13 | .env.test.local 14 | .env.production.local 15 | 16 | # Testing 17 | coverage 18 | 19 | # Turbo 20 | .turbo 21 | 22 | # Vercel 23 | .vercel 24 | 25 | # Build Outputs 26 | .next/ 27 | out/ 28 | build 29 | dist 30 | 31 | 32 | # Debug 33 | npm-debug.log* 34 | yarn-debug.log* 35 | yarn-error.log* 36 | 37 | # Misc 38 | .DS_Store 39 | *.pem 40 | -------------------------------------------------------------------------------- /mobile-magic/.npmrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/mobile-magic/.npmrc -------------------------------------------------------------------------------- /mobile-magic/README.md: -------------------------------------------------------------------------------- 1 | ## Things to do 2 | - Complete the orchestrator. Its an empty folder right now. It should talk to ASGs and scale them up/drain them when a worker becomes idle 3 | - Send the user response back to the LLM. If a user is changing a file, the LLM needs to be aware of this. 4 | - UI cleanups 5 | - Figure out why npm install doesnt work from time to time. Most probably we need to run them sequentially so create some sort of async queue to do it. 6 | - Create a load balancer service that routes requests from id.worker.100xdevs.com to the respective worker for that project 7 | - Add multiplayer mode 8 | - Backup folders to S3 (can use s3-mount for this) 9 | 10 | 11 | ## Setup procedure 12 | - Clone the project 13 | - git clone https://github.com/code100x/base-react-native-expo.git /tmp/bolty-worker 14 | - cd /tmp/bolty-worker && npm install 15 | - Build and run the code-server image 16 | ``` 17 | cd apps/code-server 18 | docker build -t code-server-update . 19 | docker run -p 8080:8080 -p 8081:8081 code-sever-update 20 | ``` 21 | - Install dependencies globally 22 | ``` 23 | bun install 24 | ``` 25 | - Start postgres locally 26 | ``` 27 | docker run -p 5432:5432 -d -e POSTGRES_PASSWORD=mysupersecretpassword postgres 28 | ``` 29 | - Copy packages/db/.env.example over to packages/db/.env 30 | - Migrate the db , generate the client 31 | ``` 32 | cd packages/db 33 | npx prisma migrate dev 34 | npx prisma generate 35 | ``` 36 | - Sign up to clerk, create a new dev app. 37 | - Start the frontend, update .env in apps/frontend 38 | ``` 39 | cd apps/frontend 40 | bun dev 41 | ``` 42 | - Copy apps/primary-backend/.env.example over to apps/primary-backend/.env, update the clerk credentials 43 | - Start the primary backend 44 | - Go to claude and get api keys, update apps/worker/.env 45 | - Start a single worker locally 46 | ``` 47 | cd apps/worker 48 | bun index.ts 49 | ``` -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | 43 | # clerk configuration (can include secrets) 44 | /.clerk/ 45 | -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. 37 | -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code100x/mobile-magic/2ee5c005dfdf034f619b1dbf6cc0d57862252fa9/mobile-magic/apps/frontend/app/favicon.ico -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { ThemeProvider } from "@/components/theme-provider" 2 | import type { Metadata } from "next" 3 | import { Figtree } from "next/font/google" 4 | import { cn } from '@/lib/utils' 5 | import { meta } from '@/lib/constants' 6 | import { Particles } from '@repo/ui/particles' 7 | import { SidebarProvider } from '@/components/ui/sidebar' 8 | import { AppSidebar } from "@/components/app-sidebar" 9 | 10 | import "./globals.css" 11 | 12 | import { ClerkProvider } from "@clerk/nextjs" 13 | 14 | const figtree = Figtree({ 15 | variable: "--font-figtree", 16 | subsets: ["latin"], 17 | weight: "300", 18 | }); 19 | 20 | export const metadata: Metadata = { 21 | title: meta.title, 22 | description: meta.description 23 | }; 24 | 25 | export default function RootLayout({ 26 | children, 27 | }: Readonly<{ 28 | children: React.ReactNode; 29 | }>) { 30 | return ( 31 | 32 | 33 | 38 | 45 | 51 | 52 | 53 | 54 | {children} 55 | 56 | 57 | 58 | 59 | 60 | ); 61 | } 62 | 63 | // grid px-4 grid-cols-[1fr_min(640px,100%)_1fr] xl:grid-cols-[1fr_minmax(auto,10rem)_min(640px,100%)_minmax(auto,10rem)_1fr] xl:gap-x-9 xl:px-0 [&>*]:col-start-2 xl:[&>*]:col-start-3 64 | 65 | -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { Prompt } from "@/components/Prompt"; 2 | import { Appbar } from "@/components/Appbar"; 3 | import { SidebarInset } from "@/components/ui/sidebar"; 4 | import { Hero } from "@/components/hero"; 5 | 6 | export default function Home() { 7 | return ( 8 | 9 |
10 |
11 |
12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 |
20 |
21 |
22 |
23 |
24 |
25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/app/project/[projectId]/page.tsx: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { K8S_ORCHESTRATOR_URL } from "@/config"; 3 | import ProjectWithInitRequest from "@/components/ProjectWithInitRequest"; 4 | 5 | interface Params { 6 | params: Promise<{ projectId: string }> 7 | } 8 | 9 | export default async function ProjectPage({ params }: Params) { 10 | const projectId = (await params).projectId 11 | const response = await axios.get(`${K8S_ORCHESTRATOR_URL}/worker/${projectId}`); 12 | const { sessionUrl, previewUrl, workerUrl } = response.data; 13 | 14 | return 20 | } 21 | -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/app/provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { ReactNode } from 'react'; 3 | import { ThemeProvider } from '@/components/theme-provider'; 4 | import { ClerkProvider } from '@clerk/nextjs' 5 | import { dark } from '@clerk/themes' 6 | 7 | export const Providers = ({ children }: { children: ReactNode }) => { 8 | return ( 9 | 13 | 19 | {children} 20 | 21 | 22 | ); 23 | }; -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/components/Appbar.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { 4 | SignInButton, 5 | SignUpButton, 6 | SignedIn, 7 | SignedOut, 8 | UserButton, 9 | } from '@clerk/nextjs' 10 | import { Header } from '@/components/Header' 11 | import { motion } from 'motion/react' 12 | import { containerVariants, itemVariants } from '@/lib/animation-variants' 13 | import { ThemeButton } from '@/components/theme-button' 14 | 15 | export function Appbar() { 16 | return ( 17 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 35 | 36 | 37 | 38 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/components/Header.tsx: -------------------------------------------------------------------------------- 1 | import { SidebarTrigger } from './ui/sidebar' 2 | import { Button } from '@/components/ui/button' 3 | import { cn } from '@/lib/utils' 4 | import Image from 'next/image' 5 | import Link from 'next/link' 6 | import { motion } from 'motion/react' 7 | import { itemVariants } from '@/lib/animation-variants' 8 | 9 | export const Header = ({ children, className, onClick }: { 10 | children?: React.ReactNode, 11 | className?: string, 12 | onClick?: () => void 13 | }) => { 14 | return ( 15 | 16 | 20 | 21 | logo 22 | 23 | {children && } 33 | 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /mobile-magic/apps/frontend/components/PreviewIframe.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { useEffect } from "react"; 3 | 4 | 5 | export function PreviewIframe({ url }: { url: string }) { 6 | const [isLoading, setIsLoading] = useState(true); 7 | 8 | useEffect(() => { 9 | console.log("interval started") 10 | const timer = setInterval(() => { 11 | console.log(`Checking if ${url} is ready`); 12 | fetch(url) 13 | .then(response => response.ok) 14 | .then(ok => { 15 | if (ok) { 16 | setIsLoading(false); 17 | } else { 18 | setIsLoading(true); 19 | } 20 | }) 21 | }, 1000); 22 | return () => clearInterval(timer); 23 | }, [url]); 24 | 25 | if (isLoading) { 26 | return
; 27 | } 28 | 29 | return ( 30 |