Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
75767f6
feat(web-domain): add Mobile API domain schemas
richiemcilroy May 19, 2026
4b46c65
chore(database): export auth domain-utils package entry
richiemcilroy May 19, 2026
6c2d63d
feat(web): add mobile HTTP API route
richiemcilroy May 19, 2026
7f3c8f7
test(web): add mobile API contract tests
richiemcilroy May 19, 2026
8197e4c
feat(web): support mobile auth deep links on login form
richiemcilroy May 19, 2026
3020100
chore(mobile): add Expo app scaffold and assets
richiemcilroy May 19, 2026
0201c68
feat(mobile): add theme and format utilities
richiemcilroy May 19, 2026
96d8d58
feat(mobile): add shared UI components
richiemcilroy May 19, 2026
92c7823
feat(mobile): add auth session and sign-in flow
richiemcilroy May 19, 2026
43d0901
feat(mobile): add mobile API client
richiemcilroy May 19, 2026
b85d871
feat(mobile): add upload queue and runner
richiemcilroy May 19, 2026
0479e9a
feat(mobile): add cap settings and metadata actions
richiemcilroy May 19, 2026
c586c58
feat(mobile): add root layout and tab navigation
richiemcilroy May 19, 2026
315ec31
feat(mobile): add dashboard tab screen
richiemcilroy May 19, 2026
16919d0
feat(mobile): add upload tab screen
richiemcilroy May 19, 2026
718a50e
feat(mobile): add account settings tab screen
richiemcilroy May 19, 2026
4bcb623
feat(mobile): add cap detail screen
richiemcilroy May 19, 2026
2289db8
chore: add dev:mobile script and react-native overrides
richiemcilroy May 19, 2026
52fd01c
chore: update lockfile for mobile workspace
richiemcilroy May 19, 2026
b879347
chore(web): refresh workflow step manifest
richiemcilroy May 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions apps/mobile/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/node_modules
.expo
/ios
/android
dist
coverage
*.tsbuildinfo

# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
# The following patterns were generated by expo-cli

expo-env.d.ts
# @end expo-cli
67 changes: 67 additions & 0 deletions apps/mobile/app.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const associatedDomains =
process.env.CAP_MOBILE_DISABLE_ASSOCIATED_DOMAINS === "1"
? []
: process.env.CAP_MOBILE_ASSOCIATED_DOMAINS
? process.env.CAP_MOBILE_ASSOCIATED_DOMAINS.split(",")
.map((domain) => domain.trim())
.filter(Boolean)
: ["applinks:cap.so"];
const bundleIdentifier = "so.cap.mobile";
const ios = {
bundleIdentifier,
supportsTablet: false,
infoPlist: {
NSPhotoLibraryUsageDescription:
"Cap imports videos from Photos for upload.",
NSPhotoLibraryAddUsageDescription: "Cap saves downloaded videos to Photos.",
UIBackgroundModes: ["processing"],
},
};

if (associatedDomains.length > 0) {
ios.associatedDomains = associatedDomains;
}

module.exports = ({ config }) => ({
...config,
name: "Cap",
slug: "cap-mobile",
scheme: "cap",
owner: "cap",
version: "0.1.0",
orientation: "portrait",
platforms: ["ios"],
userInterfaceStyle: "light",
icon: "./assets/icon.png",
splash: {
image: "./assets/splash-icon.png",
resizeMode: "contain",
backgroundColor: "#f9f9f9",
},
ios,
experiments: {
typedRoutes: true,
},
plugins: [
"expo-router",
[
"expo-font",
{
fonts: [
"../web/public/fonts/NeueMontreal-Regular.otf",
"../web/public/fonts/NeueMontreal-Medium.otf",
"../web/public/fonts/NeueMontreal-Bold.otf",
],
},
],
[
"expo-secure-store",
{
faceIDPermission: "Allow Cap to protect your account key.",
},
],
],
extra: {
apiBaseUrl: process.env.EXPO_PUBLIC_CAP_WEB_URL ?? "https://cap.so",
},
});
53 changes: 53 additions & 0 deletions apps/mobile/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { NativeTabs } from "expo-router/unstable-native-tabs";
import { colors, fonts } from "@/theme";

export default function TabsLayout() {
return (
<NativeTabs
backgroundColor={colors.glass}
blurEffect="systemMaterialLight"
disableTransparentOnScrollEdge
iconColor={{ default: colors.gray9, selected: colors.blue9 }}
labelStyle={{
default: {
color: colors.gray9,
fontFamily: fonts.medium,
fontSize: 11,
},
selected: {
color: colors.blue9,
fontFamily: fonts.medium,
fontSize: 11,
},
}}
minimizeBehavior="automatic"
shadowColor={colors.gray4}
tintColor={colors.blue9}
>
<NativeTabs.Trigger name="index">
<NativeTabs.Trigger.Label>My Caps</NativeTabs.Trigger.Label>
<NativeTabs.Trigger.Icon
sf={{ default: "folder", selected: "folder.fill" }}
/>
</NativeTabs.Trigger>
<NativeTabs.Trigger name="upload">
<NativeTabs.Trigger.Label>Import</NativeTabs.Trigger.Label>
<NativeTabs.Trigger.Icon
sf={{
default: "square.and.arrow.up",
selected: "square.and.arrow.up.fill",
}}
/>
</NativeTabs.Trigger>
<NativeTabs.Trigger name="account">
<NativeTabs.Trigger.Label>Account</NativeTabs.Trigger.Label>
<NativeTabs.Trigger.Icon
sf={{
default: "person.crop.circle",
selected: "person.crop.circle.fill",
}}
/>
</NativeTabs.Trigger>
</NativeTabs>
);
}
Loading
Loading