{"id":1847,"url":"https://github.com/mcudich/TemplateKit","last_synced_at":"2025-08-02T05:32:52.089Z","repository":{"id":56923849,"uuid":"52287953","full_name":"mcudich/TemplateKit","owner":"mcudich","description":"React-inspired framework for building component-based user interfaces in Swift.","archived":false,"fork":false,"pushed_at":"2016-11-30T00:42:11.000Z","size":1311,"stargazers_count":159,"open_issues_count":8,"forks_count":8,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-07-03T03:02:33.100Z","etag":null,"topics":["react","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mcudich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-22T16:37:14.000Z","updated_at":"2025-06-06T08:14:54.000Z","dependencies_parsed_at":"2022-08-21T05:20:28.780Z","dependency_job_id":null,"html_url":"https://github.com/mcudich/TemplateKit","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mcudich/TemplateKit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FTemplateKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FTemplateKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FTemplateKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FTemplateKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcudich","download_url":"https://codeload.github.com/mcudich/TemplateKit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcudich%2FTemplateKit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268339403,"owners_count":24234544,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react","swift"],"created_at":"2024-01-05T20:15:57.207Z","updated_at":"2025-08-02T05:32:51.809Z","avatar_url":"https://github.com/mcudich.png","language":"Swift","funding_links":[],"categories":["Reactive Programming"],"sub_categories":["React-Like","Other free courses"],"readme":"# TemplateKit\n[![Swift](https://img.shields.io/badge/swift-3-orange.svg?style=flat)](#)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/TemplateKit.svg)](https://img.shields.io/cocoapods/v/TemplateKit)\n[![Platform](https://img.shields.io/cocoapods/p/TemplateKit.svg?style=flat)](http://cocoadocs.org/docsets/TemplateKit)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)\n\n[React](http://facebook.github.io/react/)-inspired framework for building component-based user interfaces in Swift.\n\n|      | Features                                   |\n| ---- | ---------------------------------------- |\n| 🐤   | Completely native - write your app in Swift |\n| 📃   | Declarative - define your UI using markup |\n| 📦   | Components - encapsulate functionality into reusable chunks |\n| 📐   | Layout - Flexbox for layout, just like on the web |\n| 🖋   | State - automatically flush state changes to UI |\n| ⚖    | Diffing - the minimum set of updates are flushed to UI |\n| 🚀   | Performance - diffing and layout are done on background threads |\n| ⏲   | Animation - built-in support for animating any property |\n\n## Example\nYou define your UI using a simple markup language, which is inspired by HTML and CSS. This UI definition is rendered into a tree of native elements.\n\n#### Component.xml\n```html\n\u003ctemplate\u003e\n  \u003cstyle\u003e\n    #container \u003e .button {\n      color: #000;\n    }\n    \n    #container \u003e .button-selected {\n      color: #f00;\n    }\n  \u003c/style\u003e\n\n  \u003cbox id=\"container\"\u003e\n    \u003ctext text=\"$properties.title\" /\u003e\n    \u003ctext text=\"Click me!\" onTap=\"handleClick\" classNames=\"$textClasses\" /\u003e\n  \u003c/box\u003e\n\u003c/template\u003e\n```\n#### Component.swift\nFunctionality and state is encapsulated into components, which do things like handle user events and flush state changes to the UI. Components have strongly typed `State` and `Properties` values, that are used to figure out what ends up getting pushed out to UIKit.\n```swift\nstruct ComponentState: State {\n  var selected: Bool?\n}\n\nstruct ComponentProperties: Properties {\n  var core = CoreProperties()\n  var title: String? = \"This is a default title\"\n}\n\nclass MyComponent: CompositeComponent\u003cComponentState, ComponentProperties, UIView\u003e {\n  // Stored properties on the component are made available to template.\n  var textClasses: String?\n \n  // As are functions, referenced by their selector name.\n  @objc func handleClick() {\n    updateComponentState { state in\n      state.selected = !state.selected\n    }\n  }\n \n  override func render() -\u003e Element {\n    textClasses = state.selected ? \"button\" : \"button-selected\"\n  \n    return render(\"http://localhost:8000/Component.xml\")\n  }\n}\n```\n#### ViewController.swift\nRendering components is as easy as calling a `render` function, which asynchronously computes and flushes a component to the supplied container view.\n```swift\noverride func viewDidLoad() {\n  super.viewDidLoad()\n \n  UIKitRenderer.render(component(MyComponent.self), container: self.view, context: self) { component in\n    self.component = component\n  }\n}\n```\n\nSee the included [Example](https://github.com/mcudich/TemplateKit/tree/master/Example) project for more examples of how to use TemplateKit.\n\n## Why?\n\n#### Swift\nBecause you like writing your apps completely in Swift. TemplateKit is fully native and compiled.\n\n#### Declarative Style\nWriting user interfaces in a declarative style makes it easier to reason about how model data and user actions affect what gets rendered. Out-of-the-box support for XML. Extensible if you want to add your own template format (e.g., protocol buffers).\n\n#### Components\nComponents make it easy to encapsulate application functionality into re-usable building blocks. These blocks can then be composed to create more complex interfaces.\n\n#### Layout\nFlexbox-based layout primitives allow developers to use the the same expressive layout system available in modern browsers.\n\n#### Asynchronous Rendering \u0026 Performance\nAll layout computation, text sizing, tree diffing, image decoding is performed in the background. This keeps the main thread available for responding to user actions. Only the absolute minimum set of changes needed to update the view hierarchy are actually flushed to the rendered views.\n\n#### CSS\nUse stylesheets to style components, just like you do on the web.\n\n#### Animations\nAnimate layout, style and arbitrary properties using an intuitive API. \n\n#### Live Reloading\nAutomatically reload changes to user interfaces without having to re-build binaries or restart your application. Usable in both development and production environments.\n\n#### Extensible\nAdd custom components, custom native views, custom template loading schemes and more.\n\n#### Easy to try\nPlug it in anywhere you want to render a view in your application. Plays nicely with the rest of your app.\n\n## Installation\n\n#### Carthage\n\nYou can install Carthage with [Homebrew](http://brew.sh/) using the following command:\n\n```bash\n$ brew update\n$ brew install carthage\n```\n\nAdd the following line to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile):\n\n```ogdl\ngithub \"mcudich/TemplateKit\"\n```\n\nRun `carthage update`, then make sure to add `TemplateKit.framework`, `CSSLayout.framework`, and `CSSParser.framework` to \"Linked Frameworks and Libraries\" and \"copy-frameworks\" Build Phases.\n\n#### CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\nTo integrate TemplateKit into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '10.0'\nuse_frameworks!\n\ntarget '\u003cYour Target Name\u003e' do\n    pod 'TemplateKit', '~\u003e 0.1.0'\nend\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n## Requirements\n\n- iOS 9.3+\n- Xcode 8.0+\n- Swift 3.0+\n\n## Communication\n\n- If you **found a bug**, open an issue.\n- If you **have a feature request**, open an issue.\n- If you **want to contribute**, submit a pull request.\n\n## How does it work?\nAt its core, TemplateKit is comprised of `Element` and `Node` instances. Elements are used to describe trees of nodes, which can be anything that implements the `Node` interface. Nodes are used to vend out and manage view hierarchies.\n\nOut of the box, there are several `Node` implementations that make it easy to set up UI hierarchies: `Component`, `ViewNode`, and a set of native controls like buttons, text labels, text fields and so on.\n\nBuilding a component is as simple as subclassing `Component`, overriding its `render()` function, and deciding the set of properties it might accept and use as part of rendering. `render()` simply needs to return a `Template`, which can be constructed programmatically, or via an XML document (or other custom payload). When it comes time to render your component into a view, you simply call `UIKitRenderer.render`, and pass in the view that should contain your component's rendered output. This will in turn call `render()` on your component instance, compute the layout and styles for the view tree, build this tree and then apply the layout and styles to it as appropriate.\n\nWhen it comes time to update your component's state, you can call `updateState` from within your component implementation. This function receives a function that is passed the current state value (each `Component` can declare a `State` type, in the same way it declares a `Properties` type). This function in turn enqueues an update to the component, which will cause it to re-render, taking into account whatever changes were made to the state. This update is intelligent, and compares the current incarnation of the rendered view tree against the proposed element tree. Only the deltas between these two are flushed out to the view layer.\n\n## Opaque Views\nIf there are parts of your UI that are easier to deal with as plain `UIViews`, TemplateKit provides a simple abstraction `Node` called `ViewNode` that allows you to include these \"opaque\" views as part of any TemplateKit-managed tree. TemplateKit stays out of the way, and simply sets the `frame` of these views for you, so they sit nicely within in whatever UI tree you've composed.\n\n## Collections\nTemplateKit provides `UITableView` and `UICollectionView` subclasses which are able to load, and asynchronously size and render `Components` into cells with just a little bit of configuration. Tables and collections can be used via `Table` and `Collection` components, or simply wrapped as `ViewNode` instances. The `Table` and `Collection` components have built-in support for diffing, so that data-source updates result in the minimum set of operations required to have the respective UIKit views reflect data changes. See [Diff.swift](https://github.com/mcudich/TemplateKit/blob/master/Source/Utilities/Diff.swift) for more information.\n\n## How's this different from React Native?\nTemplateKit is implemented in Swift (and a bit of C). If you like writing entirely in Swift, then this framework might be for you.\n\nReact Native relies on a very well-tested library (React), and has been shipping in popular apps for some time now. This means it probably has way fewer rough edges, has sorted out many performance issues TemplateKit has yet to face, and so on.\n\n## What's Missing\nA lot.\n\nThere's no AppKit support yet (though it would be straightforward to add). Lots of tests have yet to be written. Performance testing has yet to be done. The entirety of the applicable CSS spec is not supported. Animation features are rudimentary at best. Many gesture types need to be added. And much more.\n\nIf you'd like something added, please file a feature request or send a pull request!\n\n## Inspiration\n- [React](https://github.com/facebook/react)\n- [AsyncDisplayKit](https://github.com/facebook/AsyncDisplayKit)\n\n## See Also\nIf TemplateKit isn't exactly what you're looking for, check out these other great projects!\n- [Few.swift](https://github.com/joshaber/Few.swift)\n- [Render](https://github.com/alexdrone/Render)\n- [React Native](https://facebook.github.io/react-native/)\n- [LayoutKit](https://github.com/linkedin/LayoutKit)\n- [ComponentKit](https://github.com/facebook/componentkit)\n- [HubFramework](https://github.com/spotify/HubFramework)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcudich%2FTemplateKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcudich%2FTemplateKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcudich%2FTemplateKit/lists"}