# Create a Backend Learn how to implement a backend. ## Overview In this tutorial, [TermKitBackend](https://github.com/david-swift/TermKitBackend) will be used as a sample backend to explain the elements of a backend. General information can be found in the article. ## Package Manifest Set up a new Swift Package (`swift package init`). Add the _Meta_ package as well as other dependencies if required to the dependencies section in the manifest. ```swift let package = Package( name: "TermKitBackend", platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)], products: [ .library( name: "TermKitBackend", targets: ["TermKitBackend"] ) ], dependencies: [ .package(url: "https://github.com/AparokshaUI/Meta", from: "0.1.0"), .package(url: "https://github.com/david-swift/TermKit", branch: "main") ], targets: [ .target( name: "TermKitBackend", dependencies: ["TermKit", "Meta"] ) ] ) ``` ## Backend-Specific Protocols As mentioned in , the backend has to define a backend-specific widget and scene element type. ```swift import Meta public protocol TermKitSceneElement: SceneElement { } public protocol TermKitWidget: Widget { } ``` ## The Wrapper Widget With _Meta_, arrays of ``AnyView`` have to be able to be converted into a single widget. This allows definitions such as the following one: ```swift Window { Label("Hello") Label("World") } ``` Create a widget which arranges the child views next to each other (on most platforms, doing this vertically makes most sense). It should conform to the platform-specific widget type as well as ``Wrapper``. Read the comments for general information about creating widgets. ```swift import Meta import TermKit public struct VStack: Wrapper, TermKitWidget { var content: Body public init(@ViewBuilder content: @escaping () -> Body) { // Use functions and mark them with the result builder to allow the domain-specific language to be used self.content = content() } public func container( modifiers: [(any AnyView) -> any AnyView], type: Storage.Type ) -> ViewStorage where Storage: AppStorage { let storages = content.storages(modifiers: modifiers, type: type) // Get the storages of child views if storages.count == 1 { return .init(storages[0].pointer, content: [.mainContent: storages]) } let view = View() for (index, storage) in storages.enumerated() { if let pointer = storage.pointer as? TermKit.View { view.addSubview(pointer) if let previous = (storages[safe: index - 1]?.pointer as? TermKit.View) { // The pointer should be a TermKit view pointer.y = .bottom(of: previous) } } } return .init(view, content: [.mainContent: storages]) // Save storages of child views in the parent's storage for view updates } public func update( _ storage: ViewStorage, modifiers: [(any AnyView) -> any AnyView], updateProperties: Bool, type: Storage.Type ) where Storage: AppStorage { guard let storages = storage.content[.mainContent] else { return } content.update(storages, modifiers: modifiers, updateProperties: updateProperties, type: type) // Update the storages of child views } } ``` ### Correct Updating Note that the type of the ``ViewStorage/pointer`` differs from backend to backend. It is a reference to the widget in the original UI framework. In the update method, update properties of a widget (such as a button's label) only when the `updateProperties` parameter is `true`. It indicates that a state variable (see ) of an ancestor view has been updated. If state doesn't change, it is impossible for the UI to change. However, consider the following exceptions: - _Always_ update view content (using ``AnyView/updateStorage(_:modifiers:updateProperties:type:)`` or ``Swift/Array/storages(modifiers:type:)``). Child views may contain own state. - _Always_ update closures (such as the action of a button widget). They may contain reference to state which is updated whenever a view update takes place. - _Always_ update bindings. As one can see when looking at ``Binding/init(get:set:)``, they contain two closures which, in most cases, contain a reference to state. ## The App Storage An app storage object in the app definition determines which backend to use for rendering. Therefore, it must contain information about the scene element and widget types, as well as the wrapper widget. Additionally, the function for executing the app is defined on the object, allowing you to put the setup of the UI into the correct context. The quit funtion should terminate the app. ```swift @_exported import Meta // Export the Meta package import TermKit public class TermKitApp: AppStorage { public typealias SceneElementType = TermKitSceneElement public typealias WidgetType = TermKitWidget public typealias WrapperType = VStack public var app: () -> any App public var storage: StandardAppStorage = .init() public required init(id: String, app: @escaping () -> any App) { self.app = app } public func run(setup: @escaping () -> Void) { Application.prepare() setup() Application.run() } public func quit() { Application.shutdown() } } ``` ## Next Steps Now, you can start implementing scene elements (windows or other "top-level containers"), views, and custom renderable elements. Remember following the instructions for correct updating above for all of the UI element types. If you still have questions, browse code in the [TermKitBackend repository](https://github.com/david-swift/TermKitBackend) or ask a question in the [discussions](https://github.com/AparokshaUI/Meta/discussions). Feedback on the documentation is appreciated!