SwiftUI for Web Tutorials

Learn to build declarative UIs for the web using the same patterns you love from SwiftUI. Zero dependencies, pure JavaScript.

84 Components
0 Dependencies
~88 KB Core gzipped
6 Example Apps

Example Apps

Hello World

The simplest starting point. Renders styled text with VStack layout, custom fonts, and the SwiftUI color system.

Hello World screenshot

What you'll learn

  • Creating views with Text and VStack
  • Applying Font presets (largeTitle, subheadline, body)
  • Using Color.blue, Color.green, Color.secondary
  • Modifier chaining (.font().foregroundColor().padding())
  • Mounting an App to the DOM
HelloWorld/main.js
import { App, VStack, HStack, Text, Color, Font } from '../../src/index.js';

const ContentView = () =>
  VStack({ spacing: 16 },
    Text('Hello, SwiftUI for Web!')
      .font(Font.largeTitle)
      .foregroundColor(Color.blue),
    Text('Built with pure JavaScript')
      .font(Font.subheadline)
      .foregroundColor(Color.secondary)
  ).padding(40);

App(ContentView).mount('#root');
View Live Demo

Counter

Introduces reactive State management. Clicking buttons updates the count and triggers a UI re-render automatically.

Counter screenshot

What you'll learn

  • Creating reactive state with new State(0)
  • Reading and writing state via count.value
  • Button with action callbacks
  • HStack for horizontal layout
  • Styling buttons with background, cornerRadius, padding
Counter/main.js
import { App, VStack, HStack, Text, Button, State, Color, Font }
  from '../../src/index.js';

const count = new State(0);

const CounterView = () =>
  VStack({ spacing: 24 },
    Text('Counter').font(Font.title),
    Text(String(count.value))
      .font(Font.system(72, Font.Weight.bold))
      .foregroundColor(Color.blue),
    HStack({ spacing: 16 },
      Button('\u2212', () => count.value--)
        .background(Color.red)
        .foregroundColor(Color.white)
        .cornerRadius(12),
      Button('+', () => count.value++)
        .background(Color.green)
        .foregroundColor(Color.white)
        .cornerRadius(12)
    )
  ).padding(40);
View Live Demo

Todo App

A complete MVVM application with an ObservableObject ViewModel, two-way data binding through TextField, dynamic lists with ForEach, and filter controls.

Todo App screenshot

What you'll learn

  • MVVM architecture with ObservableObject
  • Published properties for reactive state
  • Two-way binding with TextField
  • Dynamic lists using ForEach with id tracking
  • Filter logic (All / Active / Completed)
  • Computed properties (filteredTodos, activeCount)
TodoApp/main.js
class TodoViewModel extends ObservableObject {
  constructor() {
    super();
    this.published('todos', []);
    this.published('newTodoText', '');
    this.published('filter', 'all');
  }

  addTodo() {
    const text = this.newTodoText.trim();
    if (text) {
      this.todos = [...this.todos,
        new TodoItem(Date.now(), text)];
      this.newTodoText = '';
    }
  }
}

// View uses ForEach for the list
ForEach(viewModel.filteredTodos, { id: 'id' },
  (todo) => TodoItemRow(todo, viewModel)
)
View Live Demo

Netflix Clone

A rich media app with a hero banner, responsive card grids, ZStack overlays with gradient, and smooth Pinterest-style card expansion animations.

Netflix clone screenshot

What you'll learn

  • ZStack for layered hero banner with gradient overlay
  • ScrollView with horizontal and vertical scrolling
  • Responsive grid layout adapting to screen size
  • Card expansion animation outside the view tree
  • Environment and UserInterfaceSizeClass for adaptive UI
  • LinearGradient for smooth visual transitions
Netflix/main.js
// Hero banner with ZStack layering
ZStack({ alignment: 'bottomLeading' },
  Image(movie.backdrop)
    .resizable().aspectRatio('fill')
    .frame({ height: 600 }),

  LinearGradient(
    ['transparent', 'rgba(20,20,20,0.9)', '#141414'],
    { direction: 'to bottom' }
  ).frame({ height: 600 }),

  VStack({ alignment: 'leading' },
    Text(movie.title)
      .font(Font.system(56, 'bold'))
      .foregroundColor('white'),
    Button('▶ Play', () => {})
      .background('white')
      .foregroundColor('black')
  )
)
View Live Demo

StayFinder (Airbnb Clone)

A vacation rental booking app demonstrating MVVM architecture with feature-based folder structure, responsive grid listings, search with filters, and a detail view.

Airbnb clone screenshot

What you'll learn

  • Feature-based folder structure (Views/, ViewModels/, Services/)
  • Responsive grid adapting from mobile to desktop
  • Category bar navigation with filter modal
  • Listing detail view with booking flow
  • MVVM with centralized AppViewModel
  • Composing feature modules into a root app
Airbnb/main.js
import SwiftUI from '../../src/index.js';
const { App, VStack } = SwiftUI;

import { vm } from './ViewModels/AppViewModel.js';
import { Header } from './Views/Header/index.js';
import { ListingGrid, ListingDetail }
  from './Views/Listing/index.js';
import { CategoryBar, FilterModal }
  from './Views/Filter/index.js';

function MainApp() {
  return VStack({ spacing: 0 },
    Header(), CategoryBar(),
    ListingGrid(), MobileNav(),
    FilterModal(), ListingDetail()
  );
}

const app = App(MainApp).mount('#root');
vm.subscribe(() => app.refresh());
View Live Demo

Swift Charts for Web

A declarative charting library mirroring Apple's Swift Charts API. Supports bar, line, area, scatter, pie, and donut charts with the same BarMark/LineMark/SectorMark syntax.

Charts screenshot

What you'll learn

  • Chart container with data mapping callbacks
  • BarMark for categorical bar charts
  • LineMark with interpolation methods (catmullRom, monotone)
  • SectorMark for pie and donut charts
  • Multi-series with foregroundStyle(by:)
  • RuleMark for target/threshold lines
Charts/main.js
import { Chart, BarMark, LineMark, SectorMark,
  value, Color } from '../../src/index.js';

// Bar chart
Chart(salesData, item =>
  BarMark({
    x: value('Month', item.month),
    y: value('Sales', item.sales)
  })
  .foregroundStyle(Color.hex('#007AFF'))
  .cornerRadius(4)
)
.frame({ width: 500, height: 300 })
.chartXAxis({ label: 'Month' })
.chartYAxis({ label: 'Sales ($K)' });
View Live Demo

Quick Start

1

Clone the repository

No npm install required!

git clone https://github.com/ShawnBaek/SwiftUI-For-Web.git
cd SwiftUI-For-Web
2

Start a local server

ES modules require a server to work properly.

python -m http.server 8000
# or
npx serve .
3

Create your first view

Create an index.html file and start building!

<script type="module">
  import { App, VStack, Text, Color, Font }
    from './src/index.js';

  App(() =>
    VStack({ spacing: 16 },
      Text('Hello, SwiftUI for Web!')
        .font(Font.largeTitle)
        .foregroundColor(Color.blue)
    ).padding(40)
  ).mount('#root');
</script>
4

Open in browser

Visit http://localhost:8000 and see your app!