SwiftUI YouTube Home Screen
Goal:
Goal: Make Switch home screen.
Note: This is just a static page, no real functionality.
Thoughts:
I like the way it turned out. Outside of the Dalek and Peach photo, everything is a symbol. If I finish, i know I need to add the square backgrounds when a game isn't there and the highlight for whatever is currently being hovered over.

Real YouTube homepage

YouTube homepage made with SwiftUI
Code example
Here is the Swift code used to make this. Replace "peach" and "dalek" with your images. Also, notice the frame size in the main YouTubeView. I haven't learned proper scaling, so I just kept it at that scale.
import SwiftUI
struct YouTubeView: View {
@State private var text = ""
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(Color.ytBackground)
.opacity(0.5)
.clipped()
.clipShape(RoundedRectangle(cornerRadius: 18, style: .continuous))
VStack{
MenuBar()
HStack{
SideBanner()
VStack{
FilterButtonBanner()
HStack{
VideosView()
Spacer()
}
Spacer()
}
}
}
}
.frame(width: 660, height: 450)
}
}
struct VideosView: View {
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack {
HStack{
Thumbnail()
Thumbnail()
Thumbnail()
}
HStack{
Thumbnail()
Thumbnail()
Thumbnail()
}
HStack{
Thumbnail()
Thumbnail()
Thumbnail()
}
HStack{
Thumbnail()
Thumbnail()
Thumbnail()
}
}
.padding(.horizontal)
}
}
}
struct Thumbnail: View {
var verified: Bool = true
var body: some View {
Button{
print("Video Thumbnail clicked.")
}label: {
VStack(alignment: .leading) {
Image("dalek")
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 160, height: 90)
.clipped()
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.shadow(color: .black.opacity(0.1), radius: 2, x: 0, y: 3)
HStack{
VStack{
Image("peach")
.resizable()
.scaledToFill()
.frame(width: 20, height: 20)
.clipShape(Circle())
Spacer()
}
VStack{
HStack{
Text("Video Title")
.font(.system(size: 12))
Spacer()
}
HStack{
Text("Channel Name")
.font(.system(size: 10))
.foregroundStyle(.secondary)
if verified{
Image(systemName: "checkmark.circle.fill")
.font(.system(size: 8))
.foregroundStyle(.secondary)
}
Spacer()
}
HStack{
Text("123 Views • 1 hour ago")
.font(.system(size: 10))
.foregroundStyle(.secondary)
Spacer()
}
Spacer()
}
}
}
.frame(width: 160,height: 150)
.clipped()
}
.buttonStyle(.plain)
}
}
struct SideBanner: View {
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack {
NavButton(title: "Home",typeOf: "home", systemNameCh: "house.fill")
NavButton(title: "Shorts",typeOf: "home", systemNameCh: "play.square.stack")
NavDivider()
NavButton(title: "Subscriptions",typeOf: "open", systemNameCh: "chevron.right")
ForEach(0..<5) { _ in
NavButton(title: "Subscription",typeOf: "sub")
}
NavDivider()
NavButton(title: "You",typeOf: "open", systemNameCh: "chevron.right")
NavButton(title: "History",typeOf: "home",systemNameCh: "clock.arrow.trianglehead.counterclockwise.rotate.90")
NavButton(title: "Playlists",typeOf: "home",systemNameCh: "list.triangle")
NavButton(title: "Watch later",typeOf: "home",systemNameCh: "clock")
NavButton(title: "Liked videos",typeOf: "home",systemNameCh: "hand.thumbsup")
NavButton(title: "Your Videos",typeOf: "home",systemNameCh: "play.rectangle")
NavButton(title: "Show More",typeOf: "home",systemNameCh: "chevron.down")
NavDivider()
HStack{
Text("Explore")
.font(.system(size: 8))
.foregroundColor(.ytAccent)
.padding(5)
Spacer()
}
NavButton(title: "Shopping",typeOf: "home",systemNameCh: "bag")
NavButton(title: "Music",typeOf: "home",systemNameCh: "music.note")
NavButton(title: "Movies & TV",typeOf: "home",systemNameCh: "movieclapper")
NavButton(title: "Show More",typeOf: "home",systemNameCh: "chevron.down")
NavDivider()
HStack{
Text("More from Platform")
.font(.system(size: 8))
.foregroundColor(.ytAccent)
.padding(5)
Spacer()
}
NavButton(title: "Platform TV",typeOf: "home",systemNameCh: "play.tv",iconColor: .red)
NavButton(title: "Platform Music",typeOf: "home",systemNameCh: "play.circle.fill",iconColor: .red)
NavButton(title: "Platform Kids",typeOf: "home",systemNameCh: "play.house.fill",iconColor: .red)
NavDivider()
NavButton(title: "Report history",typeOf: "home",systemNameCh: "flag")
NavDivider()
VStack{
Text("About Press Copyright Contact us Creators Advertise Developers\n\nTerms Privacy Policy Status Advertising Choices")
.font(.system(size: 6))
.foregroundColor(.gray)
.padding(5)
HStack{
Image(systemName: "c.circle")
.font(.system(size: 4))
.foregroundColor(Color(.darkGray))
Text("2026 Platform LLC")
.font(.system(size: 4))
.foregroundColor(Color(.darkGray))
}
Spacer()
}
}
.padding(.horizontal)
}
.frame(width: 140)
}
}
struct NavDivider: View {
var body: some View {
Rectangle()
.frame(height: 1)
.foregroundStyle(Color(.ytButton))
.padding(5)
}
}
struct NavButton: View {
var title: String = "Hello there"
// mode, open
var typeOf: String = "mode"
var systemNameCh: String = "house.fill"
var imageNameCh: String = "peach"
var iconColor: Color = .ytAccent
var body: some View {
Button{
print(title + " clicked.")
}label: {
HStack{
if typeOf == "home"{
Image(systemName: systemNameCh)
.foregroundColor(iconColor)
}else if typeOf == "sub"{
Image("peach")
.resizable()
.scaledToFill()
.frame(width: 14, height: 14)
.clipShape(Circle())
}
// else{
// Image(systemName: "globe.americas.fill")
// }
Text(title)
.padding(.horizontal, 6)
.padding(.vertical, 5)
.font(.system(size: 8))
.foregroundColor(.ytAccent)
if typeOf == "open"{
Image(systemName: systemNameCh)
.font(.system(size: 8))
.foregroundColor(iconColor)
}
Spacer()
}
}
.buttonStyle(.plain)
}
}
struct FilterButtonBanner: View {
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<10) { _ in
FilterButton(title: "Technology")
}
}
.padding(.horizontal)
}
}
}
struct FilterButton: View {
var title: String = "Hello there"
var body: some View {
Button{
print("Filter button, \(title), clicked.")
}label: {
Text(title)
.padding(.horizontal, 6)
.padding(.vertical, 5)
.background(
Color.ytButton,
in: RoundedRectangle(cornerRadius: 4, style: .continuous)
)
.font(.system(size: 8))
.foregroundColor(.ytAccent)
}
.buttonStyle(.plain)
}
}
struct MenuBar: View {
@State private var text = ""
var body: some View {
HStack{
Button{
print("Menu button clicked.")
}label: {
HStack{
Image(systemName: "line.3.horizontal")
}
}
.buttonStyle(.plain)
.padding(.horizontal,8)
Button{
print("Platform button clicked.")
}label: {
HStack{
Image(systemName: "play.rectangle.on.rectangle.fill")
.foregroundColor(Color(.red))
Text("Platform")
}
}
.buttonStyle(.plain)
Spacer()
HStack{
ZStack{
TextField("Search", text: $text)
.clipShape(Capsule())
HStack{
Spacer()
Button{
print("Search button, \(text), clicked.")
}label: {
Image(systemName: "magnifyingglass")
}
.buttonStyle(.plain)
.padding(10)
}
}
Button{
print("Mic button clicked.")
}label: {
Image(systemName: "microphone.fill")
}
.buttonStyle(.plain)
}
.padding()
Spacer()
Button{
print("Create button clicked.")
}label: {
Image(systemName: "plus")
Text("Create")
}
.buttonStyle(.plain)
Button{
print("Bell button clicked.")
}label: {
Image(systemName: "bell")
}
.buttonStyle(.plain)
Button{
print("Profile button clicked.")
}label: {
Image("peach")
.resizable()
.scaledToFill()
.frame(width: 20, height: 20)
.clipShape(Circle())
.padding()
}
.buttonStyle(.plain)
}
.padding(.horizontal)
}
}
#Preview {
YouTubeView()
}