airbnb/MagazineLayout
A collection view layout capable of laying out views in vertically scrolling grids and lists.
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 3mo ago
- ✓14 active contributors
- ✓Apache-2.0 licensed
Show 3 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Single-maintainer risk — top contributor 82% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/airbnb/magazinelayout)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/airbnb/magazinelayout on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: airbnb/MagazineLayout
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/airbnb/MagazineLayout shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 3mo ago
- 14 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Single-maintainer risk — top contributor 82% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live airbnb/MagazineLayout
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/airbnb/MagazineLayout.
What it runs against: a local clone of airbnb/MagazineLayout — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in airbnb/MagazineLayout | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 116 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of airbnb/MagazineLayout. If you don't
# have one yet, run these first:
#
# git clone https://github.com/airbnb/MagazineLayout.git
# cd MagazineLayout
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of airbnb/MagazineLayout and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "airbnb/MagazineLayout(\\.git)?\\b" \\
&& ok "origin remote is airbnb/MagazineLayout" \\
|| miss "origin remote is not airbnb/MagazineLayout (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "MagazineLayout/Public/MagazineLayout.swift" \\
&& ok "MagazineLayout/Public/MagazineLayout.swift" \\
|| miss "missing critical file: MagazineLayout/Public/MagazineLayout.swift"
test -f "MagazineLayout/LayoutCore/ModelState.swift" \\
&& ok "MagazineLayout/LayoutCore/ModelState.swift" \\
|| miss "missing critical file: MagazineLayout/LayoutCore/ModelState.swift"
test -f "MagazineLayout/LayoutCore/SectionModel.swift" \\
&& ok "MagazineLayout/LayoutCore/SectionModel.swift" \\
|| miss "missing critical file: MagazineLayout/LayoutCore/SectionModel.swift"
test -f "MagazineLayout/LayoutCore/ItemModel.swift" \\
&& ok "MagazineLayout/LayoutCore/ItemModel.swift" \\
|| miss "missing critical file: MagazineLayout/LayoutCore/ItemModel.swift"
test -f "MagazineLayout/Public/UICollectionViewDelegateMagazineLayout.swift" \\
&& ok "MagazineLayout/Public/UICollectionViewDelegateMagazineLayout.swift" \\
|| miss "missing critical file: MagazineLayout/Public/UICollectionViewDelegateMagazineLayout.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 116 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~86d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/airbnb/MagazineLayout"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
MagazineLayout is a UICollectionViewLayout subclass for iOS that enables vertically scrolling grids and lists with flexible item widths (full-width, half-width, third-width, etc.), self-sizing in the vertical dimension, pinned headers/footers, and customizable insert/delete animations. It solves the limitation of UICollectionViewFlowLayout by supporting per-item sizing preferences, per-section spacing and inset configuration, and section backgrounds—enabling complex layouts like Airbnb's home search, wishlist, and product detail screens. Single-package structure: core layout logic resides in MagazineLayout.xcodeproj (main framework), Example/ contains four demo ViewControllers (GridDemo, ListDemo, MessageThreadDemo, PerformanceDemo) showcasing different use cases, and MagazineLayoutExampleAppleTV shows platform support. The layout is organized as a UICollectionViewLayout subclass with delegate protocol for configuration (MagazineLayoutDelegate pattern inferred from feature list).
👥Who it's for
iOS engineers at Airbnb and other companies building high-traffic, complex collection view layouts that require flexible grid/list combinations, self-sizing items, and rich animations. Particularly developers who need to move beyond UICollectionViewFlowLayout or UITableView without building custom layout logic from scratch.
🌱Maturity & risk
Production-ready and actively maintained. The codebase is 360K+ lines of Swift, used in Airbnb's production apps (documented with real screenshots), has CI/CD via GitHub Actions (.github/workflows/swift.yml), supports multiple installation methods (SPM, Carthage, CocoaPods), and includes comprehensive example apps. No visible signs of abandonment.
Low to moderate risk. Single-language codebase (Swift-only, 360K lines) with minimal external dependencies (only Ruby build tooling at 637 lines). No visible dependency explosion risk. Primary concern: UICollectionViewLayout is a complex abstraction that can be layout-calculation intensive; performance degradation with very large collections is possible. Airbnb's continued use mitigates abandonment risk, but no public commit frequency data is visible in the file structure alone.
Active areas of work
GitHub Actions workflow (.github/workflows/swift.yml) is active, indicating ongoing CI runs. Example app includes PerformanceDemoViewController and insertion/deletion animations (referencing .gif files: DeleteAnimation, InsertAnimation), suggesting recent work on animation and performance optimization. CONTRIBUTING and PULL_REQUEST_TEMPLATE documents exist, showing active contribution process.
🚀Get running
git clone https://github.com/airbnb/MagazineLayout.git && cd MagazineLayout && open MagazineLayout.xcodeproj (for framework development) or open Example/MagazineLayoutExample.xcworkspace (for example app). For SPM: add .package(url: "https://github.com/airbnb/MagazineLayout", from: "3.0.0") to Package.swift.
Daily commands: For framework: open MagazineLayout.xcodeproj and build the MagazineLayout scheme. For example app: open Example/MagazineLayoutExample.xcworkspace and run the MagazineLayoutExample scheme on iOS simulator or device. Run .github/workflows/swift.yml via xcodebuild for CLI testing: xcodebuild -workspace Example/MagazineLayoutExample.xcworkspace -scheme MagazineLayoutExample -configuration Debug.
🗺️Map of the codebase
MagazineLayout/Public/MagazineLayout.swift— Main layout class that implements UICollectionViewLayout; all contributors must understand the core layout algorithm and public API.MagazineLayout/LayoutCore/ModelState.swift— Manages the internal model state for item sizing and positioning; core to understanding how layout calculations are performed.MagazineLayout/LayoutCore/SectionModel.swift— Defines how sections are structured and laid out; essential for understanding multi-section layout logic.MagazineLayout/LayoutCore/ItemModel.swift— Represents individual items and their sizing modes; critical for item width/height calculation logic.MagazineLayout/Public/UICollectionViewDelegateMagazineLayout.swift— Delegate protocol that defines how ViewControllers configure the layout; required reading for API surface.MagazineLayout/LayoutCore/LayoutState.swift— Tracks layout state and handles content offset calculations; fundamental to understanding animation and scrolling behavior.
🛠️How to make changes
Add a new item size mode
- Define the new size mode case in the MagazineLayoutItemSizeMode enum (
MagazineLayout/Public/Types/MagazineLayoutItemSizeMode.swift) - Add width calculation logic in ItemModel.swift to handle the new mode (
MagazineLayout/LayoutCore/ItemModel.swift) - Update ModelState.swift layout computation to place items according to the new sizing (
MagazineLayout/LayoutCore/ModelState.swift) - Add unit tests in ModelStateLayoutTests.swift to validate positioning (
Tests/ModelStateLayoutTests.swift)
Add a new section configuration option
- Define the new property in MagazineLayoutSectionMetrics.swift (
MagazineLayout/LayoutCore/Types/MagazineLayoutSectionMetrics.swift) - Add corresponding delegate method to UICollectionViewDelegateMagazineLayout.swift (
MagazineLayout/Public/UICollectionViewDelegateMagazineLayout.swift) - Implement logic in ModelState.swift to use the new metric in layout calculations (
MagazineLayout/LayoutCore/ModelState.swift) - Create demo usage in a new demo view controller (
Example/MagazineLayoutExample/RootMenuViewController.swift)
Support a new supplementary view feature (e.g., sticky headers)
- Define visibility mode enum in MagazineLayoutHeaderVisibilityMode.swift (
MagazineLayout/Public/Types/MagazineLayoutHeaderVisibilityMode.swift) - Extend HeaderModel.swift to track pinning/sticky state during layout (
MagazineLayout/LayoutCore/HeaderModel.swift) - Update MagazineLayout.swift layoutAttributesForElements(in:) to reposition headers based on scroll offset (
MagazineLayout/Public/MagazineLayout.swift) - Add test in ModelStateLayoutTests.swift validating header positioning during scrolling (
Tests/ModelStateLayoutTests.swift)
🔧Why these technologies
- UICollectionViewLayout subclass — Integrates seamlessly with UICollectionView and leverages the iOS layout system for animations, scrolling, and cell recycling
- Fractional item sizing (width divisors) — Enables responsive magazine-style grids (half-width, third-width, etc.) without manual calculation, adapting to container width
- Supplementary view support (headers/footers) — Provides rich section organization beyond items, with configurable visibility and pinning for common magazine layouts
- Pixel-aligned layout — ScreenPixelAlignment utility prevents sub-pixel rendering artifacts on retina displays for crisp visual presentation
⚖️Trade-offs already made
-
Single vertical scrolling direction only (no horizontal paging)
- Why: Simplifies layout algorithm and state management; focuses on the magazine/feed use case
- Consequence: Cannot create horizontally paging layouts; developers needing multi-direction must compose with other layout types
-
Delegate-based metrics configuration (no storyboard support)
- Why: Allows dynamic, data-driven layout configuration per section without serialization overhead
- Consequence: Cannot design layouts in Interface Builder; all configuration must be done programmatically
-
Eager frame calculation in ModelState
- Why: Enables fast contentSize queries and target offset calculations for smooth scrolling
- Consequence: Higher initial layout pass time; large collections may incur visible frame-computation cost during initial setup
-
Caching attributes in LayoutState with invalidation on bounds/content change
- Why: Avoids recalculating static layout on every frame; critical for animation performance
- Consequence: Complexity managing cache invalidation; bugs can lead to stale frame data if invalidation logic is incomplete
🚫Non-goals (don't propose these)
- Does not support horizontal scrolling or multi-directional pagination
- Does not provide drag-and-drop reordering (uses standard UICollectionView APIs; client responsible for animations)
- Does not perform automatic content fetching or pagination (relies on UICollectionViewDataSource)
- Does not include built-in header/footer decoration views (clients must provide custom supplementary view controllers)
- Does not support rotation-aware layouts
🪤Traps & gotchas
No explicit env vars or service dependencies visible. Possible gotchas: (1) Self-sizing calculations are vertical-only; horizontal sizing is controlled by fractional width configuration—mixing auto-sizing in both dimensions may cause layout thrashing. (2) Pinned headers/footers require careful delegate implementation to avoid z-index conflicts. (3) UICollectionView reuse cell identifier scoping can interact unexpectedly with MagazineLayout's supplementary view caching. (4) AppleTV variant exists (MagazineLayoutExampleAppleTV) but may have platform-specific constraints not documented in visible files. (5) No visible SwiftUI support—UIKit-only.
🏗️Architecture
💡Concepts to learn
- UICollectionViewLayout Life Cycle — MagazineLayout overrides prepare(), layoutAttributesForElements(in:), and invalidation logic; understanding when these methods are called is critical for debugging layout bugs and performance issues
- Self-Sizing in One Dimension — MagazineLayout supports vertical self-sizing while fixing horizontal width to fractional values (e.g., 1/3 of available width); this constraint differs from traditional flex layouts and requires careful height estimation
- Supplementary View Caching — Headers, footers, and section backgrounds require efficient caching to avoid recalculation on every layout pass; pinned headers add z-order complexity
- Layout Invalidation & Incremental Updates — MagazineLayout supports custom insert/delete animations by managing invalidation contexts; incorrect invalidation can cause performance cliffs or visual glitches on updates
- Delegate Configuration Pattern — MagazineLayout uses delegate callbacks (inferred from feature list) for per-section sizing, spacing, and inset preferences rather than global UICollectionViewFlowLayoutDelegate; this enables flexible, fine-grained control
- Content Size Calculation for Large Collections — PerformanceDemoViewController tests layout with 1000+ items; MagazineLayout must efficiently compute total scroll content height without materializing all layout attributes at once
- Fractional Width Grids — MagazineLayout's core feature is supporting items at 1/2, 1/3, 1/4 of available width dynamically; implementing this requires custom width calculation and row-breaking logic distinct from standard grid layouts
🔗Related repos
IGListKit/IGListKit— Instagram's collection view framework supporting diffable data sources and complex layouts; alternative for apps needing more animation sophisticationairbnb/lottie-ios— Airbnb's own animation library; commonly used alongside MagazineLayout for rich insert/delete animations in production appsmozhenhao/HDCollectionViewWaterfallLayout— Pinterest-style waterfall layout for UICollectionView; similar space-filling algorithm but for unequal-height layouts (contrast)apple/swift-collections— Swift's standard collections library; MagazineLayout likely uses OrderedDictionary or similar for efficient section/item indexingpointfreeco/swiftui-navigation— Modern navigation patterns; relevant for teams modernizing UIKit-based MagazineLayout apps to SwiftUI
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for LayoutCore models (BackgroundModel, FooterModel, HeaderModel, ItemModel, SectionModel)
The MagazineLayout/LayoutCore directory contains several model files that handle critical layout computation logic, but there's no visible test directory in the file structure. These models are fundamental to the layout system and lack test coverage. Adding comprehensive unit tests would catch regressions early and make contributions safer.
- [ ] Create Tests/LayoutCore directory structure mirroring MagazineLayout/LayoutCore
- [ ] Add unit tests for BackgroundModel.swift covering initialization and property validation
- [ ] Add unit tests for HeaderModel.swift and FooterModel.swift with various sizing configurations
- [ ] Add unit tests for ItemModel.swift testing layout computation edge cases
- [ ] Add unit tests for SectionModel.swift testing multi-item section arrangements
- [ ] Add unit tests for LayoutState.swift and ModelState.swift state transitions
- [ ] Update .github/workflows/swift.yml to run these new tests in CI
Add tests for ElementLocation and ElementLocationFramePairs utility types
The Types subdirectory contains ElementLocation.swift and ElementLocationFramePairs.swift which are critical for coordinate/frame mapping in the layout system. These utility types likely have complex logic (frame calculations, element positioning) that should be tested, especially for edge cases with different section/item combinations.
- [ ] Create Tests/LayoutCore/Types directory
- [ ] Add unit tests for ElementLocation.swift covering initialization, equality, and edge cases
- [ ] Add unit tests for ElementLocationFramePairs.swift testing frame pair associations and lookups
- [ ] Add unit tests for IDGenerator.swift ensuring unique ID generation under various scenarios
- [ ] Add unit tests for CollectionViewUpdateItem.swift covering update tracking scenarios
Add AppleTV target tests and update CI workflow for tvOS support
The repo includes MagazineLayoutExampleAppleTV target but .github/workflows/swift.yml likely only tests iOS. AppleTV (tvOS) has different layout constraints and focus engine behavior. Adding dedicated tvOS unit tests and CI coverage would ensure the layout works correctly across Apple platforms.
- [ ] Create a new test target in MagazineLayout.xcodeproj for tvOS
- [ ] Add platform-specific unit tests in Tests/ covering tvOS focus engine compatibility
- [ ] Create a new GitHub Actions workflow (.github/workflows/tvos.yml) that builds and tests for tvOS destination
- [ ] Update swift.yml to also run tests on the tvOS simulator
- [ ] Document tvOS-specific testing requirements in Docs/CONTRIBUTING.md
🌿Good first issues
- Add unit tests for PerformanceDemoViewController: create Tests/ directory with XCTest suite validating layout time complexity with 1000+ items and measuring memory usage. Current file list has no Tests/ folder despite production code.
- Document delegate protocol methods with code examples: README mentions per-section spacing, insets, and sizing preferences but Example/ ViewControllers show implementation. Create Docs/DelegateProtocolGuide.md with detailed method signatures and use cases for each configuration callback.
- Add SwiftUI wrapper example: create Example/MagazineLayoutExample/SwiftUIDemoViewController.swift showing how to wrap MagazineLayout in UIViewControllerRepresentable; solves modern app integration pain point not currently addressed.
⭐Top contributors
Click to expand
Top contributors
- @bryankeller — 81 commits
- @elfredpagan — 4 commits
- @nate-sentjens — 2 commits
- @dfed — 2 commits
- @jinxiao-zang — 1 commits
📝Recent commits
Click to expand
Recent commits
c940309— Fix the contentOffsetAdjustment when overscrolling (#154) (bryankeller)b46f8a0— Update links in README.md (bryankeller)3ee1ad2— Reduce index path lookups (#152) (bryankeller)013e301— Improve performance of layout model IDs (#151) (bryankeller)ae34a35— Fix targetContentOffsetAnchor calculation (#150) (bryankeller)3a67f1a— Bk/fix preferred attributes content offset adjustment (#149) (bryankeller)ad1ff37— Bk/add layout state (#148) (bryankeller)ac3466a— Bk/improve example projects (#147) (bryankeller)113c5f4— Make verticalLayoutDirection configurable after initialization (#146) (bryankeller)545707d— Bk/refactor model state batch updates (#145) (bryankeller)
🔒Security observations
MagazineLayout is a UI layout library with minimal security risk. No critical vulnerabilities were identified. The codebase appears to be a well-maintained Apple framework with no apparent injection risks, hardcoded secrets, or dangerous patterns. The main recommendations are establishing a security policy for responsible disclosure and ensuring dependency management best practices are documented. The library's focus on UI layout logic naturally limits exposure to common web-based vulnerabilities (SQLi, XSS). Infrastructure and CI/CD pipelines use standard GitHub workflows without exposed secrets in visible configuration.
- Low · Missing SECURITY.md or Security Policy —
Repository root. The repository does not contain a SECURITY.md file or security policy document. This makes it difficult for security researchers to responsibly disclose vulnerabilities. Fix: Create a SECURITY.md file following GitHub's security policy guidelines, outlining how to report security vulnerabilities privately. - Low · No dependency lock file visible —
Repository root / Package management files. While this is a framework library without explicit third-party dependencies listed, the lack of visible Package.resolved or Podfile.lock in the provided file structure could indicate incomplete dependency management documentation. Fix: Ensure all dependency management files (Package.resolved, Podfile.lock) are committed to version control and regularly updated.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.