Agent skill
Paperand Development
Guide for developing and maintaining the Paperand React Native manga reader application
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/paperback-android
SKILL.md
Paperand Development Skill
This skill provides comprehensive guidance for working with the Paperand project - an ad-free manga reader built with Expo and React Native, compatible with Paperback extensions.
Project Overview
Paperand is a cross-platform manga reader app that:
- Provides an elegant, ad-free manga reading experience
- Is compatible with Paperback extension sources
- Supports both Android and iOS platforms
- Features a personal library, reading progress tracking, and multi-source search
Tech Stack
| Technology | Purpose |
|---|---|
| Expo SDK 54 | Development framework |
| React Native 0.81 | Cross-platform mobile development |
| TypeScript | Type-safe JavaScript |
| React Navigation 7 | Navigation library (stack + bottom tabs) |
| AsyncStorage | Persistent local storage |
| expo-image | Optimized image loading with caching |
| WebView | Extension runtime for Paperback sources |
| i18n-js | Internationalization |
Project Structure
paperback-android/
├── App.tsx # Main app entry, providers setup
├── index.ts # Expo entry point
├── app.json # Expo configuration
├── package.json # Dependencies
├── src/
│ ├── components/ # Reusable UI components
│ │ ├── MangaCard.tsx # Manga cover card component
│ │ ├── ChapterListItem.tsx # Chapter list item
│ │ ├── ExtensionRunner.tsx # WebView extension runtime
│ │ ├── PickerModal.tsx # Custom picker modal
│ │ └── ...
│ ├── context/ # React Context providers
│ │ ├── ThemeContext.tsx # Theme management
│ │ └── LibraryContext.tsx # Library & progress state
│ ├── navigation/ # Navigation configuration
│ │ ├── AppNavigator.tsx # Main stack navigator
│ │ └── BottomTabNavigator.tsx # Bottom tab navigation
│ ├── screens/ # App screens
│ │ ├── LibraryScreen.tsx # User library
│ │ ├── DiscoverScreen.tsx # Browse sources
│ │ ├── SearchScreen.tsx # Multi-source search
│ │ ├── MangaDetailScreen.tsx # Manga details & chapters
│ │ ├── ReaderScreen.tsx # Manga reader (core feature)
│ │ ├── DownloadManagerScreen.tsx # Download management
│ │ ├── ExtensionsScreen.tsx # Manage extensions
│ │ └── ...
│ ├── services/ # Core business logic
│ │ ├── sourceService.ts # Extension API bridge
│ │ ├── extensionService.ts # Extension management
│ │ ├── cacheService.ts # Image caching
│ │ ├── downloadService.ts # Chapter downloads
│ │ ├── themeService.ts # Theme file parsing
│ │ ├── i18nService.ts # Internationalization
│ │ ├── updateService.ts # App update checks
│ │ └── ...
│ ├── hooks/ # Custom React hooks
│ ├── types/ # TypeScript type definitions
│ ├── constants/ # App constants
│ └── locales/ # Translation files (17 languages)
├── android/ # Android native code
├── assets/ # Images, icons, fonts
├── plugins/ # Custom Expo config plugins
└── credentials/ # Build credentials
Development Commands
# Install dependencies
npm install
# or
bun install
# Start development server
npx expo start
# Run on Android
npm run android
# Run on iOS
npm run ios
# Run on web
npm run web
Key Architectural Patterns
1. Extension System
The app uses a WebView-based extension runtime (ExtensionRunner.tsx) to execute Paperback-compatible extensions. Extensions are JavaScript bundles that provide manga source implementations.
2. Context Providers
- ThemeContext: Manages app theme (dark/light mode) and custom
.pbcolorsthemes - LibraryContext: Manages user library, favorites, reading progress, and history
3. Service Layer
All business logic is encapsulated in service files:
sourceService.ts- Bridge between app and extensionscacheService.ts- Image caching with configurable limitsdownloadService.ts- Background chapter downloadsi18nService.ts- Multi-language support
4. Navigation Structure
Stack Navigator (AppNavigator)
├── Bottom Tab Navigator
│ ├── Library
│ ├── Discover
│ ├── History
│ └── More
├── MangaDetail
├── Reader
├── Search
├── Extensions
├── Settings
└── ...
Internationalization (i18n)
The app supports 17+ languages. Translation files are in src/locales/ as JSON files.
Adding a new translation:
- Create a new JSON file in
src/locales/(e.g.,de.json) - Copy the structure from
en.json - Translate all strings
- Register the language in
i18nService.ts
Theming
The app supports custom themes via .pbcolors files (Paperback theme format).
Theme configuration:
- System theme support (automatic dark/light mode)
- Custom color parsing in
themeService.ts - Theme application via
ThemeContext
Building for Production
GitHub Actions (Automated)
On push to main or manual trigger:
- Builds Android APK with signing
- Builds iOS IPA
- Creates GitHub Release with artifacts
Local EAS Build
# Android APK
eas build --platform android --profile preview
# iOS
eas build --platform ios --profile preview
Common Development Tasks
Adding a New Screen
- Create the screen component in
src/screens/ - Export it from
src/screens/index.ts - Add the route in
src/navigation/AppNavigator.tsx - Add navigation types if using TypeScript
Adding a New Component
- Create the component in
src/components/ - Export it from
src/components/index.ts - Use the theme from
ThemeContextfor styling
Adding a New Service
- Create the service file in
src/services/ - Use AsyncStorage for persistent data
- Follow existing patterns for async operations
Code Style Guidelines
- Use TypeScript for all new files
- Use functional components with hooks
- Use the app's theme system for colors (
useTheme()) - Use
i18n.t('key')for all user-facing strings - Keep components focused and reusable
- Use services for business logic, not in components
Testing & Debugging
- Developer Menu: Tap version number in More > About 7 times
- Console Logging: Use standard
console.log(visible in Metro bundler) - React Native Debugger: Connect via Expo dev tools
Important Notes
- The app uses Expo managed workflow with custom native code via config plugins
- Background downloads require foreground service configuration (Android)
- Extension execution happens in an isolated WebView context
- Image caching is handled by expo-image with custom cache management
Quick Reference
Import Patterns
// Theme & Styles
import { useTheme } from '../context/ThemeContext';
// Library & State
import { useLibrary } from '../context/LibraryContext';
// Navigation
import { useNavigation, useRoute } from '@react-navigation/native';
// Components
import { MangaCard, LoadingIndicator, EmptyState } from '../components';
// Services
import { sourceService } from '../services/sourceService';
import { cacheService } from '../services/cacheService';
// i18n
import { i18n } from '../services/i18nService';
Screen Template
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { useTheme } from '../context/ThemeContext';
export function NewScreen() {
const { colors } = useTheme();
return (
<View style={[styles.container, { backgroundColor: colors.background }]}>
{/* Content */}
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
});
Navigation Params
// Navigate with params
navigation.navigate('MangaDetail', { manga, sourceId });
navigation.navigate('Reader', { manga, chapter, sourceId });
// Get params
const { manga, sourceId } = useRoute().params;
Styling Patterns
Theme Colors
const { colors, isDark } = useTheme();
// colors.background, colors.text, colors.primary, colors.card, colors.border
Common Styles
// Card style
{ backgroundColor: colors.card, borderRadius: 12, padding: 16 }
// Text styles
{ color: colors.text, fontSize: 16 }
{ color: colors.textSecondary, fontSize: 14 }
// Separator
{ height: 1, backgroundColor: colors.border }
State Management
Library Context Methods
const {
library, // Manga[] - saved manga
favorites, // string[] - favorite manga IDs
readingProgress, // { [mangaId]: { chapterId, page } }
addToLibrary, // (manga) => void
removeFromLibrary, // (mangaId) => void
toggleFavorite, // (mangaId) => void
updateProgress, // (mangaId, chapterId, page) => void
} = useLibrary();
AsyncStorage Keys
| Key | Type | Description |
|---|---|---|
@library |
Manga[] | Saved manga |
@favorites |
string[] | Favorite IDs |
@reading_progress |
object | Reading positions |
@extensions |
Extension[] | Installed extensions |
@settings |
object | User settings |
@history |
HistoryItem[] | Reading history |
Extension API
Source Service Methods
// Get manga list
await sourceService.getDiscoverSection(sourceId, sectionId);
// Search manga
await sourceService.searchManga(sourceId, query);
// Get manga details
await sourceService.getMangaDetails(sourceId, mangaId);
// Get chapters
await sourceService.getChapters(sourceId, mangaId);
// Get chapter pages
await sourceService.getChapterPages(sourceId, chapterId);
Error Handling
try {
const data = await sourceService.getMangaDetails(sourceId, mangaId);
} catch (error) {
console.error('Failed to load manga:', error);
// Show error state or toast
}
Performance Tips
- Images: Use
expo-imagewithcachePolicy="memory-disk" - Lists: Use
FlatListwithkeyExtractorandgetItemLayout - Memoization: Use
useMemo/useCallbackfor expensive operations - Lazy Loading: Load chapters/pages on demand
File Naming
| Type | Convention | Example |
|---|---|---|
| Screen | *Screen.tsx |
LibraryScreen.tsx |
| Component | PascalCase.tsx |
MangaCard.tsx |
| Service | *Service.ts |
cacheService.ts |
| Hook | use*.ts |
useDebounce.ts |
| Context | *Context.tsx |
ThemeContext.tsx |
| Types | index.ts |
types/index.ts |
Troubleshooting
| Issue | Solution |
|---|---|
| Extension not loading | Check WebView logs, verify extension URL |
| Images not caching | Check cache size limits in settings |
| Build fails | Run npx expo prebuild --clean |
| Metro bundler stuck | Clear cache: npx expo start -c |
| Android foreground service crash | Check withBackgroundActionsServiceType plugin |
Android-Specific
- Foreground service type configured in
plugins/withBackgroundActionsServiceType.js - Permissions in
app.jsonunderandroid.permissions - Deep links:
paperback://andpaperand://schemes
iOS-Specific
- Background modes:
fetchenabled - Localization: 35+ locales in
CFBundleLocalizations - Bundle ID:
com.chiraitori.paperand.ios
Didn't find tool you were looking for?