opencode-skills-collection 3.0.41 → 3.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +10 -0
  2. package/bundled-skills/.antigravity-install-manifest.json +3 -1
  3. package/bundled-skills/2slides-ppt-generator/SKILL.md +8 -18
  4. package/bundled-skills/accesslint-diff/SKILL.md +5 -2
  5. package/bundled-skills/android-dev/SKILL.md +524 -0
  6. package/bundled-skills/android-dev/references/flutter.md +269 -0
  7. package/bundled-skills/android-dev/references/hybrid.md +158 -0
  8. package/bundled-skills/android-dev/references/java-android.md +586 -0
  9. package/bundled-skills/android-dev/references/kmm.md +206 -0
  10. package/bundled-skills/android-dev/references/native-android.md +239 -0
  11. package/bundled-skills/android-dev/references/react-native.md +242 -0
  12. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  13. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  14. package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
  15. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  16. package/bundled-skills/docs/users/bundles.md +1 -1
  17. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  18. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  19. package/bundled-skills/docs/users/getting-started.md +1 -1
  20. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  21. package/bundled-skills/docs/users/usage.md +4 -4
  22. package/bundled-skills/docs/users/visual-guide.md +4 -4
  23. package/bundled-skills/event-staffing-ordering/SKILL.md +2 -17
  24. package/bundled-skills/unship/SKILL.md +138 -0
  25. package/package.json +1 -1
  26. package/skills_index.json +44 -0
@@ -0,0 +1,269 @@
1
+ # Flutter Reference (Dart)
2
+
3
+ ## Project Structure
4
+
5
+ ```
6
+ lib/
7
+ ├── main.dart # Entry point
8
+ ├── app/
9
+ │ ├── app.dart # MaterialApp + router setup
10
+ │ ├── theme/ # ThemeData, colors, typography, spacing
11
+ │ └── router/ # go_router config, guards
12
+ ├── features/
13
+ │ └── home/
14
+ │ ├── data/
15
+ │ │ ├── datasource/ # Remote + local data sources
16
+ │ │ ├── dto/ # JSON models (freezed)
17
+ │ │ └── repository/ # Repo implementations
18
+ │ ├── domain/
19
+ │ │ ├── model/ # Domain models (freezed)
20
+ │ │ ├── repository/ # Abstract repo interfaces
21
+ │ │ └── usecase/ # Use cases
22
+ │ └── presentation/
23
+ │ ├── bloc/ # Bloc/Cubit + state + event
24
+ │ └── screen/ # Widgets + page files
25
+ ├── core/
26
+ │ ├── network/ # Dio client, interceptors
27
+ │ ├── database/ # Drift DB setup
28
+ │ ├── widgets/ # Shared design system widgets
29
+ │ └── error/ # Failure types, error handling
30
+ └── injection.dart # GetIt service locator setup
31
+ ```
32
+
33
+ ## State Management (BLoC)
34
+
35
+ ```dart
36
+ // States
37
+ @freezed
38
+ class HomeState with _$HomeState {
39
+ const factory HomeState.initial() = _Initial;
40
+ const factory HomeState.loading() = _Loading;
41
+ const factory HomeState.success(List<Item> items) = _Success;
42
+ const factory HomeState.failure(String message) = _Failure;
43
+ }
44
+
45
+ // Events
46
+ @freezed
47
+ class HomeEvent with _$HomeEvent {
48
+ const factory HomeEvent.loadItems() = _LoadItems;
49
+ const factory HomeEvent.refreshItems() = _RefreshItems;
50
+ }
51
+
52
+ // Bloc
53
+ class HomeBloc extends Bloc<HomeEvent, HomeState> {
54
+ final GetItemsUseCase _getItems;
55
+
56
+ HomeBloc(this._getItems) : super(const HomeState.initial()) {
57
+ on<_LoadItems>(_onLoad);
58
+ }
59
+
60
+ Future<void> _onLoad(_LoadItems event, Emitter<HomeState> emit) async {
61
+ emit(const HomeState.loading());
62
+ final result = await _getItems();
63
+ result.fold(
64
+ (failure) => emit(HomeState.failure(failure.message)),
65
+ (items) => emit(HomeState.success(items)),
66
+ );
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## State Management (Riverpod — alternative)
72
+
73
+ ```dart
74
+ @riverpod
75
+ class HomeNotifier extends _$HomeNotifier {
76
+ @override
77
+ FutureOr<List<Item>> build() => _load();
78
+
79
+ Future<List<Item>> _load() async {
80
+ final repo = ref.read(itemRepositoryProvider);
81
+ return repo.getItems().getOrThrow();
82
+ }
83
+
84
+ Future<void> refresh() async {
85
+ state = const AsyncLoading();
86
+ state = await AsyncValue.guard(_load);
87
+ }
88
+ }
89
+ ```
90
+
91
+ ## Screen Widget Pattern
92
+
93
+ ```dart
94
+ class HomeScreen extends StatelessWidget {
95
+ const HomeScreen({super.key});
96
+
97
+ @override
98
+ Widget build(BuildContext context) {
99
+ return BlocProvider(
100
+ create: (ctx) => sl<HomeBloc>()..add(const HomeEvent.loadItems()),
101
+ child: const _HomeView(),
102
+ );
103
+ }
104
+ }
105
+
106
+ class _HomeView extends StatelessWidget {
107
+ const _HomeView();
108
+
109
+ @override
110
+ Widget build(BuildContext context) {
111
+ return Scaffold(
112
+ body: BlocConsumer<HomeBloc, HomeState>(
113
+ listener: (ctx, state) {
114
+ state.maybeWhen(
115
+ failure: (msg) => ScaffoldMessenger.of(ctx)
116
+ .showSnackBar(SnackBar(content: Text(msg))),
117
+ orElse: () {},
118
+ );
119
+ },
120
+ builder: (ctx, state) => state.when(
121
+ initial: () => const SizedBox(),
122
+ loading: () => const Center(child: CircularProgressIndicator()),
123
+ success: (items) => _ItemList(items: items),
124
+ failure: (msg) => ErrorView(message: msg,
125
+ onRetry: () => ctx.read<HomeBloc>().add(
126
+ const HomeEvent.loadItems())),
127
+ ),
128
+ ),
129
+ );
130
+ }
131
+ }
132
+ ```
133
+
134
+ ## go_router Setup
135
+
136
+ ```dart
137
+ final router = GoRouter(
138
+ initialLocation: '/home',
139
+ redirect: (context, state) {
140
+ final isLoggedIn = ref.read(authStateProvider).isLoggedIn;
141
+ if (!isLoggedIn && !state.matchedLocation.startsWith('/auth')) {
142
+ return '/auth/login';
143
+ }
144
+ return null;
145
+ },
146
+ routes: [
147
+ GoRoute(
148
+ path: '/home',
149
+ name: AppRoutes.home,
150
+ builder: (ctx, state) => const HomeScreen(),
151
+ routes: [
152
+ GoRoute(
153
+ path: 'detail/:id',
154
+ builder: (ctx, state) =>
155
+ DetailScreen(id: state.pathParameters['id']!),
156
+ ),
157
+ ],
158
+ ),
159
+ ],
160
+ );
161
+ ```
162
+
163
+ ## Drift Database
164
+
165
+ ```dart
166
+ @DriftDatabase(tables: [Items])
167
+ class AppDatabase extends _$AppDatabase {
168
+ AppDatabase(QueryExecutor e) : super(e);
169
+
170
+ @override
171
+ int get schemaVersion => 1;
172
+
173
+ Stream<List<Item>> watchAllItems() =>
174
+ (select(items)..orderBy([(t) => OrderingTerm.desc(t.updatedAt)])).watch();
175
+
176
+ Future<void> upsertItems(List<ItemsCompanion> rows) =>
177
+ batch((b) => b.insertAllOnConflictUpdate(items, rows));
178
+ }
179
+ ```
180
+
181
+ ## Key pubspec.yaml Dependencies
182
+
183
+ ```yaml
184
+ dependencies:
185
+ flutter_bloc: ^8.1.5
186
+ freezed_annotation: ^2.4.1
187
+ riverpod: ^2.5.1 # alternative to bloc
188
+ flutter_riverpod: ^2.5.1
189
+ go_router: ^14.1.0
190
+ dio: ^5.4.3
191
+ drift: ^2.18.0
192
+ sqflite: ^2.3.3
193
+ get_it: ^7.7.0
194
+ injectable: ^2.4.1
195
+ dartz: ^0.10.1 # Either/Option for FP error handling
196
+ json_annotation: ^4.9.0
197
+
198
+ dev_dependencies:
199
+ build_runner: ^2.4.9
200
+ freezed: ^2.5.2
201
+ json_serializable: ^6.8.0
202
+ drift_dev: ^2.18.0
203
+ mocktail: ^1.0.3
204
+ bloc_test: ^9.1.7
205
+ ```
206
+
207
+ ## Error Handling (Either/Failure pattern)
208
+
209
+ ```dart
210
+ abstract class Failure {
211
+ final String message;
212
+ const Failure(this.message);
213
+ }
214
+
215
+ class NetworkFailure extends Failure {
216
+ const NetworkFailure([super.message = 'Network error occurred']);
217
+ }
218
+
219
+ class CacheFailure extends Failure {
220
+ const CacheFailure([super.message = 'Cache error occurred']);
221
+ }
222
+
223
+ // Repository
224
+ Future<Either<Failure, List<Item>>> getItems() async {
225
+ try {
226
+ final remote = await _remoteSource.fetchItems();
227
+ await _localSource.saveItems(remote);
228
+ return Right(remote.map(_mapper.toDomain).toList());
229
+ } on DioException catch (e) {
230
+ return Left(NetworkFailure(e.message ?? 'Network error'));
231
+ } on Exception {
232
+ return const Left(CacheFailure());
233
+ }
234
+ }
235
+ ```
236
+
237
+ ## Testing
238
+
239
+ ```dart
240
+ void main() {
241
+ group('HomeBloc', () {
242
+ late HomeBloc bloc;
243
+ late MockGetItemsUseCase mockUseCase;
244
+
245
+ setUp(() {
246
+ mockUseCase = MockGetItemsUseCase();
247
+ bloc = HomeBloc(mockUseCase);
248
+ });
249
+
250
+ tearDown(() => bloc.close());
251
+
252
+ blocTest<HomeBloc, HomeState>(
253
+ 'emits [loading, success] when loadItems succeeds',
254
+ build: () {
255
+ when(() => mockUseCase()).thenAnswer(
256
+ (_) async => Right([Item(id: '1', title: 'Test')]),
257
+ );
258
+ return bloc;
259
+ },
260
+ act: (b) => b.add(const HomeEvent.loadItems()),
261
+ expect: () => [
262
+ const HomeState.loading(),
263
+ isA<HomeState>().having((s) => s, 'success',
264
+ const HomeState.success([Item(id: '1', title: 'Test')])),
265
+ ],
266
+ );
267
+ });
268
+ }
269
+ ```
@@ -0,0 +1,158 @@
1
+ # Hybrid Android Reference (Capacitor + Ionic / React)
2
+
3
+ ## When to Use Hybrid
4
+
5
+ ✅ Good fit:
6
+ - Web team building a companion Android app
7
+ - Content-heavy apps (news, docs, forms)
8
+ - PWA upgrade to installable app
9
+ - Rapid prototyping
10
+
11
+ ❌ Avoid for:
12
+ - Real-time games / heavy animations
13
+ - Deep native sensor / hardware access
14
+ - Apps requiring 60fps custom animations
15
+ - Bluetooth/NFC intensive apps (use plugins, but complex)
16
+
17
+ ## Stack Options
18
+
19
+ | Option | UI Framework | Best For |
20
+ |--------|-------------|---------|
21
+ | Capacitor + Ionic | Ionic components | Full mobile-optimized UI |
22
+ | Capacitor + React | React + Tailwind | Web team reuse |
23
+ | Capacitor + Vue | Vue + Ionic | Vue teams |
24
+ | Capacitor + Angular | Angular + Ionic | Enterprise Angular teams |
25
+
26
+ ## Project Structure (Capacitor + React)
27
+
28
+ ```
29
+ src/
30
+ ├── App.tsx
31
+ ├── pages/ # Screen components
32
+ ├── components/ # Shared UI components
33
+ ├── hooks/ # Business logic hooks
34
+ ├── services/ # API, storage services
35
+ └── store/ # State management
36
+ android/ # Native Android project (generated)
37
+ ├── app/src/main/
38
+ │ ├── AndroidManifest.xml
39
+ │ └── java/.../MainActivity.kt
40
+ capacitor.config.ts # Capacitor configuration
41
+ ```
42
+
43
+ ## Capacitor Config
44
+
45
+ ```typescript
46
+ // capacitor.config.ts
47
+ import { CapacitorConfig } from '@capacitor/cli';
48
+
49
+ const config: CapacitorConfig = {
50
+ appId: 'com.example.app',
51
+ appName: 'My App',
52
+ webDir: 'dist',
53
+ server: {
54
+ androidScheme: 'https',
55
+ },
56
+ android: {
57
+ buildOptions: {
58
+ releaseType: 'APK', // or AAB for Play Store
59
+ },
60
+ },
61
+ plugins: {
62
+ SplashScreen: {
63
+ launchShowDuration: 0,
64
+ backgroundColor: '#FFFFFF',
65
+ },
66
+ PushNotifications: {
67
+ presentationOptions: ['badge', 'sound', 'alert'],
68
+ },
69
+ },
70
+ };
71
+ ```
72
+
73
+ ## Native Plugin Usage
74
+
75
+ ```typescript
76
+ import { Camera, CameraResultType } from '@capacitor/camera';
77
+ import { Preferences } from '@capacitor/preferences';
78
+ import { PushNotifications } from '@capacitor/push-notifications';
79
+ import { Geolocation } from '@capacitor/geolocation';
80
+
81
+ // Camera
82
+ const takePhoto = async () => {
83
+ const photo = await Camera.getPhoto({
84
+ quality: 90,
85
+ allowEditing: false,
86
+ resultType: CameraResultType.Uri,
87
+ });
88
+ return photo.webPath;
89
+ };
90
+
91
+ // Secure storage
92
+ const saveToken = async (token: string) => {
93
+ await Preferences.set({ key: 'auth_token', value: token });
94
+ };
95
+
96
+ const getToken = async (): Promise<string | null> => {
97
+ const { value } = await Preferences.get({ key: 'auth_token' });
98
+ return value;
99
+ };
100
+
101
+ // Push notifications
102
+ const initPush = async () => {
103
+ const permission = await PushNotifications.requestPermissions();
104
+ if (permission.receive === 'granted') {
105
+ await PushNotifications.register();
106
+ }
107
+ PushNotifications.addListener('registration', ({ value: token }) => {
108
+ console.log('FCM Token:', token);
109
+ });
110
+ };
111
+ ```
112
+
113
+ ## Performance Best Practices
114
+
115
+ - Ensure hardware acceleration is enabled for the application in AndroidManifest.xml (default in Capacitor)
116
+ - Enable HTTP caching in Android WebView settings
117
+ - Lazy-load routes with React.lazy / dynamic imports
118
+ - Avoid `setTimeout`/`setInterval` for animations; use CSS transitions
119
+ - Use `@ionic/react` components — they handle mobile-specific touch handling
120
+ - Ionic virtual scroll for long lists
121
+
122
+ ## Build & Deploy
123
+
124
+ ```bash
125
+ # Build web assets
126
+ npm run build
127
+
128
+ # Sync to native
129
+ npx cap sync android
130
+
131
+ # Open in Android Studio
132
+ npx cap open android
133
+
134
+ # Build release APK/AAB via Android Studio or:
135
+ cd android && ./gradlew bundleRelease
136
+ ```
137
+
138
+ ## Custom Native Plugin (when built-in plugins don't cover it)
139
+
140
+ ```kotlin
141
+ // android/app/src/main/java/.../MyPlugin.kt
142
+ @CapacitorPlugin(name = "MyPlugin")
143
+ class MyPlugin : Plugin() {
144
+ @PluginMethod
145
+ fun doNativeWork(call: PluginCall) {
146
+ val value = call.getString("input") ?: return call.reject("No input")
147
+ // Do native work
148
+ val result = JSObject()
149
+ result.put("output", "processed: $value")
150
+ call.resolve(result)
151
+ }
152
+ }
153
+
154
+ // TypeScript usage
155
+ import { registerPlugin } from '@capacitor/core';
156
+ const MyPlugin = registerPlugin<{ doNativeWork: (opts: { input: string }) => Promise<{ output: string }> }>('MyPlugin');
157
+ const result = await MyPlugin.doNativeWork({ input: 'hello' });
158
+ ```