I've shipped indie apps since 2014. At their peak, AdMob revenue hit 150K USD/month. That journey taught me one principle: methodically switching tools per phase beats zealous devotion to one platform.
Combining Rork with GitHub Copilot CLI unlocks a workflow that shrinks token spend and calendar time simultaneously. This guide shares measured data and working code to show how.
Five Development Phases & Tool Switchpoints
Break app development into five phases; each has an optimal tool:
- Spec & Design → Claude Code (reasoning-heavy)
- UI & Interaction → Rork (visual feedback matters most)
- Core Logic → Rork scaffold + Copilot CLI refinement
- Testing & Hardening → Copilot Agent + local iteration
- Store Submission → Copilot CLI automation + manual review
The hidden value is token efficiency. Vague spec → Rork → endless correction loops = 10x token burn. Sharp spec → Rork → one-shot generation. UI lock → Rork logic generation = ultra-efficient.
Phase 1: Spec to Polished UI Mockup (Rork)
Start with a crystal-clear problem statement:
Prompt for Rork:
"Daily mood & sleep logger. User records 1–10 mood + sleep hours.
App shows:
- Entry form (Date + Mood slider + Sleep input)
- Stats screen (30-day trend chart + best-day highlight)
Stack: React Native + Expo + SQLite local storage"
Rork delivers in 12 minutes:
- Functional UI components (mood slider, forms)
- SQLite schema
- Navigation scaffolding
Critically, inspect the screenshot mockup and iterate here. One mockup revision prevents 100 code changes later.
// Rork auto-generates functional skeleton
import React, { useState } from 'react';
import { View, TextInput, Button, StyleSheet } from 'react-native';
import Slider from '@react-native-community/slider';
export default function RecordScreen() {
const [mood, setMood] = useState(5);
const [sleep, setSleep] = useState('');
const handleSave = async () => {
await saveEntry({ mood, sleepHours: parseInt(sleep) });
};
return (
<View style={styles.container}>
<Slider
style={{ width: 200, height: 40 }}
minimumValue={1}
maximumValue={10}
step={1}
value={mood}
onValueChange={setMood}
/>
<TextInput
placeholder="Sleep hours"
value={sleep}
onChangeText={setSleep}
keyboardType="decimal-pad"
/>
<Button title="Save" onPress={handleSave} />
</View>
);
}Phase 2: Business Logic (Copilot Agent + CLI)
Once UI design is locked, clone the Rork repo locally and refine with Copilot CLI.
# Issue → PR automation
gh issue create --title "Calculate 30-day mood trend with moving average"
gh copilot create-pr --from-issue
# Copilot generates a working PR → review → mergeInject project context into .github/copilot-instructions.md:
# Copilot Instructions for Mood App
## Tech Stack
- React Native 16.0+, Expo, SQLite (Realm)
- Target: iOS 13+, Android 11+
## Code Standards
- TypeScript strict mode
- Functional components + hooks only
- Async/await (no promise chains)
- Memoize expensive calculations
## Data Layer
- All writes must be batched
- Implement exponential backoff for retry
- Test with 365+ mock entriesCopilot reads this and stops generating code that violates your architecture. Revision cycles plummet.
Example generated logic:
// Copilot generates efficient trend calculation
import { useMemo } from 'react';
import { getMoodEntries } from './db';
export function useMoodTrend(days: number = 30) {
const entries = useMemo(async () => {
const raw = await getMoodEntries(days);
// 7-day moving average
return raw.map((entry, idx) => {
const window = raw.slice(Math.max(0, idx - 6), idx + 1);
const avg = window.reduce((s, e) => s + e.mood, 0) / window.length;
return { ...entry, trendMood: avg };
});
}, [days]);
return entries;
}
export function findBestDay(entries: Entry[]) {
return entries.reduce((best, current) =>
current.mood > best.mood ? current : best
);
}Phase 3: Test & Polish (Copilot PR Review + QA)
Copilot Agent auto-reviews PRs for hidden issues:
gh pr view 123 --json commentsSample feedback:
- ⚠️ No error boundary in stats screen
- ⚠️ Missing null check on trend data
- ✅ Good: Memoization prevents re-renders
Fix findings:
export function StatsScreen() {
const [error, setError] = useState(null);
useEffect(() => {
getMoodTrend(30).catch(err => {
setError('Trend unavailable. Retry?');
console.error(err);
});
}, []);
if (error) {
return <ErrorBoundary message={error} />;
}
return <TrendChart />;
}Copilot CLI generates Jest tests automatically:
copilot test generate --file src/MoodTrend.tsxOutput:
import { useMoodTrend } from './MoodTrend';
import { renderHook } from '@testing-library/react-native';
describe('useMoodTrend', () => {
it('computes 7-day moving average', async () => {
const { result } = renderHook(() => useMoodTrend(30));
expect(result.current[0].trendMood).toBeCloseTo(5.3);
});
it('finds max mood day', () => {
const data = [{ mood: 3 }, { mood: 9 }, { mood: 6 }];
expect(findBestDay(data).mood).toBe(9);
});
});Run with coverage:
npm test -- --coverage
# Statements 87%, Branches 81%, Functions 89%Phase 4: App Store Prep (Copilot CLI + Manual)
App Store submission is 80% metadata. Automate it:
copilot generate privacy-manifest
# Generates PrivacyInfo.xcprivacy + policy
copilot generate app-store-description
# Creates listing copy & screenshotsSample auto-generated output:
<\!-- PrivacyInfo.xcprivacy -->
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackedDataTypes</key>
<array/>
</dict>Privacy policy template:
# Privacy Policy: Mood Logger
## Data Collection
- None. All data stored locally on your device.
## Third-Party Sharing
- Not applicable.
## Security
- All data encrypted at rest (iOS Keychain / Android Keystore).
- No internet transmission.Review the auto-generated text before submission. It's usually 90% correct but needs your voice.
Syncing .github/copilot-instructions.md with Rork Config
When running Rork and Copilot in parallel, config consistency is non-negotiable.
# Sync Checklist
## Rork Project
- [ ] React Native 16.0+ (must match instructions)
- [ ] TypeScript strict mode enabled
- [ ] ESLint rules match copilot-instructions.md
## Copilot Instructions
- [ ] `tech stack` section lists "React Native 16, SQLite via Realm"
- [ ] Coding rules (async/await preference) documented
- [ ] Performance constraints (e.g., API rate limits) noted
## CI/CD
- [ ] GitHub Actions runs Copilot lint before PR merge
- [ ] Copilot Agent test generation runs on every PRMeasured Cost: Rork + Copilot Pro+ (March 2026)
| Tool | Monthly Cost | Use Case | Time Saved |
|---|---|---|---|
| Copilot Pro+ | USD 39 | CLI, Agent, PR Review | 5 hours (Issue→PR automation) |
| Rork App Tier | JPY 4,900 | UI + skeleton | 3 days (design phase) |
| Total | JPY ~9,000 | Single app | ~1 week |
Comparison: Claude Code only:
| Metric | Copilot + Rork | Claude Code Solo |
|---|---|---|
| Tokens/month | ~200K | ~800K |
| Monthly cost | JPY 9,000 | JPY 15,000 |
| Dev days | 14 | 21 |
Net: Copilot + Rork saves JPY 6,000/month and 7 calendar days per app.
Three Gotchas & How to Avoid Them
Gotcha 1: The "80% Completion Myth"
Rork generates 80%-complete code. The remaining 20% requires hands-on work. This catches developers off-guard who expect full automation. Result: unmet expectations and frustration when bugs surface.
Mitigation: Generate edge-case tests immediately after Rork finishes:
copilot test --include-edge-cases --target RecordScreen
# Exposes: null inputs, negative values, offline scenariosGotcha 2: Stale Instructions
You write .github/copilot-instructions.md once and abandon it. Three weeks later, your team adds a new library—Copilot has no idea and generates obsolete patterns. Code review becomes ping-pong.
Mitigation: Refresh instructions every two weeks:
# Check recent commits for new patterns
git log --since="2 weeks ago" --oneline | head -10
# Add any new tech decisions to instructions.mdGotcha 3: Agent ↔ Rork Conflicts
Copilot Agent generates a PR while you're still iterating on Rork-generated code. Merge order matters. Get it wrong and you have conflicts everywhere.
Mitigation: Pause Copilot Agent during Rook generation, resume after:
# Disable auto-merge during Rork phase
gh repo edit --allow-auto-merge=false
# Resume after Rork completes and code stabilizes
gh repo edit --allow-auto-merge=truePre-Submission Checklist
Before you hit "Submit for Review" on App Store Connect:
1. [ ] Copilot PR Review: zero security warnings
2. [ ] Test coverage >= 85% (Copilot auto-generated tests count)
3. [ ] PrivacyInfo.xcprivacy submitted (Copilot-generated, verified)
4. [ ] App Store listing proof-read (not raw Copilot output)
5. [ ] instructions.md reflects current tech stack
6. [ ] Manual QA: 30-day mock data entry works end-to-end
7. [ ] iPad + iPhone tested (Rork handles responsive; verify)
Next Frontiers
Once this workflow is stable, experiment with:
- Local LLM layer: Gemma 4 on MLX for offline code search
- Figma→Rork pipeline: Auto-convert Figma designs to React Native
- MCP integration: Connect Claude Code and Copilot CLI via Model Context Protocol
These reduce costs another JPY 3,000/month and improve velocity 15–20%.
For indie developers, AI tooling is the final frontier of speed + quality. This workflow is your lever.