Complete developer workflow and best practices.
-
Install Prerequisites
- Android Studio Hedgehog+
- JDK 17
- Node.js 18+
- Git
-
Clone & Setup
git clone <repo-url> cd cc # Backend cd backend npm install cp .env.example .env # Edit .env with your Plaid credentials npm start # Android # Open in Android Studio # Sync Gradle # Run on device/emulator
git checkout -b feature/my-featureAndroid:
- Follow MVVM architecture
- Use Kotlin coroutines
- Write unit tests
- Update documentation
Backend:
- Follow layered architecture
- Use async/await
- Write tests
- Update API docs
# Android
./gradlew test
./gradlew connectedAndroidTest
# Backend
cd backend
npm test
npm run coverage # Must be 95%+# Android
./gradlew ktlintFormat
./gradlew ktlintCheck
# Backend
npm run lint:fix
npm run formatgit add .
git commit -m "feat: add my feature"Commit Message Format:
feat: New featurefix: Bug fixdocs: Documentationstyle: Formattingrefactor: Code restructuringtest: Testschore: Maintenance
git push origin feature/my-featureCreate pull request on GitHub.
Android:
app/src/main/java/com/ccoptimizer/app/
├── business/ # Business logic
├── data/ # Data layer
├── ui/ # UI layer
├── utils/ # Utilities
└── MainActivity.kt # Entry point
Backend:
backend/src/
├── config/ # Configuration
├── middleware/ # Express middleware
├── services/ # Business logic
├── repositories/ # Data access
└── utils/ # Utilities
1. Use Kotlin Idioms:
// ✅ Good
val name = user?.name ?: "Unknown"
// ❌ Avoid
val name = if (user != null) user.name else "Unknown"2. Use Coroutines:
// ✅ Good
viewModelScope.launch {
val data = repository.getData()
}
// ❌ Avoid
Thread {
val data = repository.getData()
}.start()3. State Management:
// ✅ Good: StateFlow
private val _state = MutableStateFlow<UiState>(UiState.Loading)
val state: StateFlow<UiState> = _state.asStateFlow()
// ❌ Avoid: LiveData in new code
private val _state = MutableLiveData<UiState>()1. Use Async/Await:
// ✅ Good
async function getData() {
const data = await db.query('SELECT * FROM users');
return data;
}
// ❌ Avoid
function getData() {
return db.query('SELECT * FROM users').then(data => data);
}2. Error Handling:
// ✅ Good
try {
const data = await api.getData();
return data;
} catch (error) {
logger.error('Error:', error);
throw error;
}3. Input Validation:
// ✅ Always validate
const validation = [
body('email').isEmail(),
body('password').isLength({ min: 8 })
];Logcat:
adb logcat | grep "CC_OPTIMIZER"Breakpoints:
- Set in Android Studio
- Run in Debug mode (Shift+F9)
Logging:
logger.debug('Debug message');
logger.info('Info message');
logger.error('Error message');Node Inspector:
node --inspect server.jsUnit Tests:
@Test
fun `test payment calculation`() {
val card = CreditCard(statementDay = 18, ...)
val recommendation = PaymentCalculator.calculateRecommendation(card)
assertEquals(LocalDate.of(2025, 10, 15), recommendation.recommendedPaymentDate)
}UI Tests:
@Test
fun testMainScreen() {
composeTestRule.setContent {
MainScreen(viewModel)
}
composeTestRule.onNodeWithText("Connect with Plaid").assertExists()
}Unit Tests:
describe('AuthService', () => {
it('should register user', async () => {
const result = await authService.register('test@example.com', 'password');
expect(result.user.email).toBe('test@example.com');
});
});Update docs when adding features:
- API changes → Update
docs/api/ - New features → Update
docs/features/ - Architecture changes → Update
docs/architecture/
Run backend:
cd backend
npm startBuild Android debug:
./gradlew assembleDebugBuild Android release:
./gradlew getCertificatePins -PBACKEND_URL=https://your-backend.com
./gradlew assembleReleaseRun tests:
./gradlew test # Android unit tests
npm test # Backend testsFix linting:
./gradlew ktlintFormat # Android
npm run lint:fix # BackendSee Also: