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

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 YTPivotBarViewsetRenderer: 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:

%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):

// 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 YTPivotBarItemViewsetRenderer: method clears button titles when removeLabels is enabled:

%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:

%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:

%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:

%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:

%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 YTPivotBarViewsetRenderer: — 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 YTPivotBarViewControllerviewDidAppear: — Shorts-only mode and default tab selection
YTLite.x 33-38 %hook YTAppViewControllershowPivotBar — prevents bar show in Shorts-only mode

Summary

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

  • Settings layerSettings.x provides a user-friendly picker interface with 8+ toggle switches that persist preferences using ytlBool/ytlSetBool
  • Tab filtering layer%hook YTPivotBarViewsetRenderer: 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 layerYTPivotBarViewController 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 YTAppViewControllershowPivotBar (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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →