# How YTLite Modifies the YouTube Tab Bar Navigation: A Complete Technical Breakdown

> Discover how YTLite modifies YouTube tab bar navigation using MobileSubstrate hooks. Learn to hide, reorder, and customize tabs dynamically for a personalized experience.

- Repository: [Dan/YTLite](https://github.com/dayanch96/YTLite)
- Tags: deep-dive
- Published: 2026-04-22

---

**YTLite modifies the YouTube tab bar navigation by injecting preference-driven hooks into `YTPivotBarView`, `YTPivotBarItemView`, and `YTPivotBarIndicatorView` using MobileSubstrate, allowing users to hide, reorder, and customize tabs at runtime.**

YTLite is a popular iOS tweak that enhances the YouTube app with extensive customization options. One of its most powerful features is **tab bar navigation modification** — the ability to remove unwanted tabs, restore the Explore tab, hide labels and indicators, and even enable a "Shorts-only" mode. This deep dive examines the actual source code from the `dayanch96/YTLite` repository to explain exactly how these modifications work.

## How YTLite Settings Control the Tab Bar

The YTLite tab bar modification system begins in the **Settings panel**, where users toggle preferences that are stored as boolean values and later read by the runtime hooks.

### The Tabbar Settings Section in Settings.x

In **`Settings.x`** (lines 76-93), YTLite constructs a dedicated **Tabbar** section containing multiple toggle switches:

| Setting | Preference Key | Effect |
|---------|-------------|--------|
| Remove Labels | `removeLabels` | Hides tab title text |
| Remove Indicators | `removeIndicators` | Hides notification dots/badges |
| Re-Explore | `reExplore` | Restores Explore tab if removed |
| Add Explore | `addExplore` | Forces Explore tab to appear |
| Hide Shorts Tab | `removeShorts` | Removes Shorts tab |
| Hide Subscriptions Tab | `removeSubscriptions` | Removes Subscriptions tab |
| Hide Upload Button | `removeUploads` | Removes Upload tab |
| Hide Library Tab | `removeLibrary` | Removes Library tab |

Each switch uses helper methods `ytlBool` and `ytlSetBool` to read and persist these preferences, which are then accessed by the runtime hooks in `YTLite.x`.

## Core Tab Bar Modification Logic in YTLite.x

The primary tab bar modification occurs in **`YTLite.x`** through MobileSubstrate hooks targeting `YTPivotBarView`. The `%hook YTPivotBarView` → `setRenderer:` method (lines 44-78) implements the complete tab filtering and insertion logic.

### How YTLite Filters and Removes Tabs

The hook intercepts the pivot bar renderer before it displays and modifies its `itemsArray`:

```objc
%hook YTPivotBarView
- (void)setRenderer:(YTIPivotBarRenderer *)renderer {
    NSMutableArray<YTIPivotBarSupportedRenderers *> *items = [renderer itemsArray];
    
    // Map tab identifiers to their removal conditions
    NSDictionary *identifiersToRemove = @{
        @"FEshorts": @[@(ytlBool(@"removeShorts")), @(ytlBool(@"reExplore"))],
        @"FEsubscriptions": @[@(ytlBool(@"removeSubscriptions"))],
        @"FEuploads": @[@(ytlBool(@"removeUploads"))],
        @"FElibrary": @[@(ytlBool(@"removeLibrary"))]
    };
    
    // Iterate and remove matching tabs
    for (NSString *identifier in identifiersToRemove) {
        BOOL shouldRemove = [identifiersToRemove[identifier] containsObject:@(YES)];
        if (shouldRemove) {
            NSUInteger idx = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *r, NSUInteger i, BOOL *stop) {
                return [[[r pivotBarItemRenderer] pivotIdentifier] isEqualToString:identifier];
            }];
            if (idx != NSNotFound) [items removeObjectAtIndex:idx];
        }
    }
    
    // Explore tab insertion logic (shown below)...
    
    %orig;
}
%end

```

The code uses `indexOfObjectPassingTest:` to find tabs by their `pivotIdentifier` (YouTube's internal tab IDs like `FEshorts`, `FEsubscriptions`, etc.) and removes them from the mutable array before the original `setRenderer:` implementation processes the modified list.

### How YTLite Adds or Restores the Explore Tab

The same hook optionally **inserts** the Explore tab when it's missing and either `reExplore` or `addExplore` is enabled (lines 69-76):

```objc
// Inside setRenderer: hook, after removal logic
NSUInteger exploreIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *r, NSUInteger i, BOOL *stop) {
    return [[[r pivotBarItemRenderer] pivotIdentifier] isEqualToString:@"FEexplore"];
}];

if (exploreIndex == NSNotFound && (ytlBool(@"reExplore") || ytlBool(@"addExplore"))) {
    YTIPivotBarSupportedRenderers *exploreTab = [%c(YTIPivotBarRenderer) 
        pivotBarItemWithPivotIdentifier:@"FEexplore" 
        title:LOC(@"Explore") 
        iconImageName:@"icons_system_explore_24"];
    [items insertObject:exploreTab atIndex:1];
}

```

This creates a new `YTIPivotBarSupportedRenderers` item using YouTube's internal factory method and inserts it at index 1 (second position) in the tab bar.

## Hiding Tab Labels and Indicators

Beyond removing entire tabs, YTLite can also **visually minimize** the tab bar by hiding text labels and notification indicators.

### Removing Tab Labels in YTPivotBarItemView

In **`YTLite.x`** lines 90-97, the `%hook YTPivotBarItemView` → `setRenderer:` method clears button titles when `removeLabels` is enabled:

```objc
%hook YTPivotBarItemView
- (void)setRenderer:(YTIPivotBarRenderer *)renderer {
    %orig;
    if (ytlBool(@"removeLabels")) {
        [self.navigationButton setTitle:@"" forState:UIControlStateNormal];
        [self.navigationButton setSizeWithPaddingAndInsets:NO];
    }
}
%end

```

The `setSizeWithPaddingAndInsets:NO` call ensures the button resizes appropriately without text content.

### Removing Notification Indicators in YTPivotBarIndicatorView

For indicators (the small dots showing new content), **`YTLite.x`** lines 84-86 hooks `YTPivotBarIndicatorView`:

```objc
%hook YTPivotBarIndicatorView
- (void)setFillColor:(id)arg1 { %orig(ytlBool(@"removeIndicators") ? [UIColor clearColor] : arg1); }
- (void)setBorderColor:(id)arg1 { %orig(ytlBool(@"removeIndicators") ? [UIColor clearColor] : arg1); }
%end

```

This forces both fill and border colors to transparent when indicators should be hidden, making them invisible while preserving the view structure.

## Default Tab Selection and Shorts-Only Mode

YTLite provides additional navigation control through **default tab selection** and a specialized **Shorts-only mode**.

### Setting the Default Tab in YTPivotBarViewController

In **`YTLite.x`** lines 118-124, the `viewDidAppear:` hook reads the `pivotIndex` preference and selects the corresponding tab:

```objc
%hook YTPivotBarViewController
- (void)viewDidAppear:(BOOL)animated {
    %orig;
    NSInteger pivotIndex = ytlInt(@"pivotIndex");
    if (pivotIndex > 0 && [self.viewControllers count] >= pivotIndex) {
        [self selectItemWithPivotIdentifier:self.viewControllers[pivotIndex - 1].pivotIdentifier];
    }
}
%end

```

The `pivotIndex` is 1-based in the UI but converted to 0-based array access, allowing users to set any tab as their default landing page.

### Enabling Shorts-Only Mode

For users who want a dedicated Shorts experience, **`YTLite.x`** lines 18-24 implement `shortsOnlyMode`:

```objc
%hook YTPivotBarViewController
- (void)viewDidAppear:(BOOL)animated {
    %orig;
    if (ytlBool(@"shortsOnlyMode")) {
        [self selectItemWithPivotIdentifier:@"FEshorts"];
        [self.parentViewController hidePivotBar];
    }
    // ... default tab logic
}
%end

```

This hook automatically selects the Shorts tab (`FEshorts`) and hides the entire pivot bar, creating a fullscreen Shorts-only interface.

### Preventing Pivot Bar Show in Shorts-Only Mode

To ensure the bar stays hidden, **`YTLite.x`** lines 33-38 hooks `YTAppViewController`:

```objc
%hook YTAppViewController
- (void)showPivotBar {
    if (ytlBool(@"shortsOnlyMode")) {
        %orig(NO);
    } else {
        %orig;
    }
}
%end

```

This intercepts `showPivotBar` calls and passes `NO` when `shortsOnlyMode` is active, suppressing any automatic bar visibility.

## Key Implementation Files

| File | Lines | Purpose |
|------|-------|---------|
| `Settings.x` | 76-93 | Defines the Tabbar settings UI with toggle switches for all tab bar modifications |
| `YTLite.x` | 44-78 | `%hook YTPivotBarView` → `setRenderer:` — core logic for removing and adding tabs |
| `YTLite.x` | 69-76 | Explore tab insertion logic when `reExplore` or `addExplore` is enabled |
| `YTLite.x` | 84-86 | `%hook YTPivotBarIndicatorView` — hides notification indicators |
| `YTLite.x` | 90-97 | `%hook YTPivotBarItemView` — removes tab labels |
| `YTLite.x` | 18-24 | `%hook YTPivotBarViewController` → `viewDidAppear:` — Shorts-only mode and default tab selection |
| `YTLite.x` | 33-38 | `%hook YTAppViewController` → `showPivotBar` — prevents bar show in Shorts-only mode |

## Summary

YTLite modifies the YouTube tab bar navigation through a sophisticated multi-layered injection system:

- **Settings layer** — `Settings.x` provides a user-friendly picker interface with 8+ toggle switches that persist preferences using `ytlBool`/`ytlSetBool`
- **Tab filtering layer** — `%hook YTPivotBarView` → `setRenderer:` in `YTLite.x` intercepts the pivot bar renderer, maps YouTube's internal identifiers (`FEshorts`, `FEsubscriptions`, `FEuploads`, `FElibrary`) to preferences, and removes matching tabs from the `itemsArray`
- **Tab insertion layer** — The same hook conditionally creates and inserts an `Explore` tab (`FEexplore`) at index 1 when `reExplore` or `addExplore` is enabled
- **Visual minimization layer** — Separate hooks on `YTPivotBarItemView` and `YTPivotBarIndicatorView` hide labels and notification indicators without removing the underlying tab structure
- **Navigation control layer** — `YTPivotBarViewController` hooks implement default tab selection via `pivotIndex` and the complete "Shorts-only" mode that auto-selects Shorts and hides the entire bar

## Frequently Asked Questions

### What is the pivot bar in YouTube's iOS app?

The **pivot bar** is YouTube's internal name for the bottom navigation tab bar that contains tabs like Home, Shorts, Subscriptions, and Library. YTLite hooks into `YTPivotBarView`, `YTIPivotBarRenderer`, and related classes to modify this component at runtime. The bar uses identifiers like `FEshorts`, `FEsubscriptions`, `FEuploads`, `FElibrary`, and `FEexplore` to distinguish tabs internally.

### Can YTLite completely remove the tab bar instead of just hiding tabs?

Yes, through **Shorts-only mode**. When `shortsOnlyMode` is enabled in `YTLite.x` lines 18-24, the tweak calls `[self.parentViewController hidePivotBar]` and also hooks `YTAppViewController` → `showPivotBar` (lines 33-38) to prevent the bar from reappearing. This creates a fullscreen Shorts experience without the bottom navigation bar entirely.

### How does YTLite restore the Explore tab that YouTube removed?

YTLite checks if the `FEexplore` identifier exists in the current `itemsArray` within the `setRenderer:` hook (lines 69-76). If `exploreIndex == NSNotFound` and either `reExplore` or `addExplore` is enabled, it constructs a new `YTIPivotBarSupportedRenderers` instance using `%c(YTIPivotBarRenderer)`'s factory method with the title "Explore" and icon `icons_system_explore_24`, then inserts it at index 1 (second position).

### Why does YTLite use separate hooks for labels and indicators instead of one hook?

YTLite uses **targeted hooks** for visual modifications because labels and indicators are rendered by separate view classes with different responsibilities. `YTPivotBarItemView` manages the button containing the icon and label, so hooking `setRenderer:` there (lines 90-97) allows clearing the title string. `YTPivotBarIndicatorView` is a separate sublayer for notification badges, so hooking `setFillColor:` and `setBorderColor:` (lines 84-86) forces transparent colors. This separation follows the actual view hierarchy in YouTube's UIKit implementation.