api-pagination
Platform Notes
- Optional helper plugins may help in some environments, but they must not be treated as required for this skill.
API Pagination Skill
Acknowledgement: Shared by Peter Bamuhigire, techguypeter.com, +256 784 464178.
Use When
- Offset pagination pattern for PHP REST APIs and mobile clients (Android Jetpack Compose + iOS SwiftUI). Covers backend response format, client DTOs, repository, ViewModel state, and infinite-scroll UI. Use when adding pagination to any list endpoint.
- The task needs reusable judgment, domain constraints, or a proven workflow rather than ad hoc advice.
Do Not Use When
- The task is unrelated to
api-paginationor would be better handled by a more specific companion skill. - The request only needs a trivial answer and none of this skill's constraints or references materially help.
Required Inputs
- Gather relevant project context, constraints, and the concrete problem to solve; load
referencesonly as needed. - Confirm the desired deliverable: design, code, review, migration plan, audit, or documentation.
Workflow
- Read this
SKILL.mdfirst, then load only the referenced deep-dive files that are necessary for the task. - Apply the ordered guidance, checklists, and decision rules in this skill instead of cherry-picking isolated snippets.
- Produce the deliverable with assumptions, risks, and follow-up work made explicit when they matter.
Quality Standards
- Keep outputs execution-oriented, concise, and aligned with the repository's baseline engineering standards.
- Preserve compatibility with existing project conventions unless the skill explicitly requires a stronger standard.
- Prefer deterministic, reviewable steps over vague advice or tool-specific magic.
Anti-Patterns
- Treating examples as copy-paste truth without checking fit, constraints, or failure modes.
- Loading every reference file by default instead of using progressive disclosure.
Outputs
- A concrete result that fits the task: implementation guidance, review findings, architecture decisions, templates, or generated artifacts.
- Clear assumptions, tradeoffs, or unresolved gaps when the task cannot be completed from available context alone.
- References used, companion skills, or follow-up actions when they materially improve execution.
Evidence Produced
| Category | Artifact | Format | Example |
|---|---|---|---|
| Correctness | Pagination test plan | Markdown doc covering offset, limit, edge cases (empty, last page, oversized), and stable sort | docs/api/pagination-tests.md |
References
- Use the
references/directory for deep detail after reading the core workflow below.
Overview
Standard offset-based pagination pattern used across the Maduuka platform. Applies to the PHP backend (REST API) and mobile clients (Android Kotlin + Compose, iOS SwiftUI).
Pattern: Backend returns data.items[] + data.pagination{}. Mobile clients append items on scroll, track page/totalPages in ViewModel state.
Deployment: Backend runs on Windows dev (MySQL 8.4.7), Ubuntu staging (MySQL 8.x), Debian production (MySQL 8.x). Pagination queries must use utf8mb4_unicode_ci collation and work identically on all platforms.
PHP Backend Pattern
Response Format (MANDATORY)
Every paginated list endpoint MUST return this structure:
{
"success": true,
"data": {
"items": [ ... ],
"pagination": {
"page": 1,
"per_page": 30,
"total": 142,
"total_pages": 5
}
}
}
PHP Implementation Template
<?php
declare(strict_types=1);
require_once __DIR__ . '/../middleware.php';
require_method('GET');
$auth = require_auth();
$db = get_db();
$franchiseId = (int)$auth['franchise_id'];
$page = max(1, (int)($_GET['page'] ?? 1));
$perPage = min(100, max(1, (int)($_GET['per_page'] ?? 30)));
// Optional filters
$status = isset($_GET['status']) ? trim((string)$_GET['status']) : '';
try {
$where = 't.franchise_id = :fid';
$params = ['fid' => $franchiseId];
if ($status !== '') {
$where .= ' AND t.status = :status';
$params['status'] = $status;
}
// 1. Count total
$countSql = "SELECT COUNT(*) FROM tbl_example t WHERE {$where}";
$countStmt = $db->prepare($countSql);
$countStmt->execute($params);
$total = (int)$countStmt->fetchColumn();
$countStmt->closeCursor(); // IMPORTANT for PDO
$totalPages = $total > 0 ? (int)ceil($total / $perPage) : 1;
$offset = ($page - 1) * $perPage;
// 2. Fetch page
$sql = "SELECT t.* FROM tbl_example t WHERE {$where}
ORDER BY t.created_at DESC
LIMIT :lim OFFSET :off";
$queryParams = $params;
$queryParams['lim'] = $perPage;
$queryParams['off'] = $offset;
$stmt = $db->prepare($sql);
foreach ($queryParams as $key => $value) {
if ($key === 'lim' || $key === 'off') {
$stmt->bindValue($key, $value, PDO::PARAM_INT);
} else {
$stmt->bindValue($key, $value);
}
}
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 3. Return with pagination metadata
json_response(200, [
'success' => true,
'data' => [
'items' => $rows,
'pagination' => [
'page' => $page,
'per_page' => $perPage,
'total' => $total,
'total_pages' => $totalPages,
],
],
]);
} catch (Throwable $e) {
json_response(500, [
'success' => false,
'message' => 'Failed to load items',
'error' => $e->getMessage(),
]);
}
Key PHP Rules
- Always
closeCursor()after the COUNT query before running the main query (PDO requirement). - Bind LIMIT/OFFSET as
PDO::PARAM_INT— string binding causes MySQL errors. - Cap
per_pageat 100 to prevent abuse:min(100, max(1, ...)). - Default
per_pageis 30 for list screens, 50 for stock-level screens. - Response shape is
data.items+data.pagination— NEVER return a flat array indata.
Additional Guidance
Extended guidance for api-pagination was moved to references/skill-deep-dive.md to keep this entrypoint compact and fast to load.
Use that deep dive for:
Android Client PatternKey Compose Imports for PaginationiOS Client PatternImportant RulesExisting Implementations
More from peterbamuhigire/skills-web-dev
google-play-store-review
Google Play Store compliance and review readiness for Android apps. Use
76multi-tenant-saas-architecture
Use when designing or reviewing a multi-tenant SaaS platform — tenant
62jetpack-compose-ui
Jetpack Compose UI standards for beautiful, sleek, minimalistic Android
49gis-mapping
Use for web apps that need Leaflet-first GIS mapping, location selection,
48saas-accounting-system
Implement a complete double-entry accounting system inside any SaaS app.
47manual-guide
Generate end-user manuals and reference guides for ERP modules. Use when
38