<!-- example.html -->
<div
id="example"
style="width:50px;height:25px"
/>
<!-- example.html -->
<div
id="example"
style="width:50px;height:25px"
/>
Div(attrs = { attr("id", "example") style { property("width", 50.px) property("height", 25.px) } })
Div(attrs = { attr("id", "example") style { property("width", 50.px) property("height", 25.px) } })
Div(attrs = { attr("id", "example") style { property("width", 50.px) property("height", 25.px) } })
Div(attrs = { attr("id", "example") style { property("width", 50.px) property("height", 25.px) } })
<!-- example.html -->
<div
id="example"
style="width:50px;height:25px"
/>
Div(attrs = { id("example") style { width(50.px) height(25.px) } })
/* example.css */
.rect {
width: 50px;
height: 25px;
}
<!-- example.html --> <div id="example" class="rect" />
<!-- example.html --> <div id="example" class="rect" />
<!-- example.html --> <div id="example" class="rect" />
/* example.css */ .rect { width: 50px; height: 25px; }
<!-- example.html --> <div id="example" class="rect" />
object AppStyleSheet : StyleSheet() { val rect by style { width(50.px) height(50.px) } }
object AppStyleSheet : StyleSheet() { val rect by style { width(50.px) height(50.px) } }
Div(attrs = { id("example") classes( AppStyleSheet.rect ) })
Div(attrs = { id("example") classes( AppStyleSheet.rect ) })
@Page
@Composable
fun AboutPage() {
/* ... */
}
# Title
## Subtitle
Great for blog posts or about pages!
Modifier
Box
, Row
, Column
# Homebrew: Mac / Linux
$ brew install varabyte/tap/kobweb
# Scoop: Windows
> scoop install varabyte/kobweb
# SDKMAN! Mac / Windows / *nix
$ sdk install kobweb
plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.jetbrains.compose) alias(libs.plugins.kobweb.application) alias(libs.plugins.kobwebx.markdown) } kobweb { app { index { description.set("Powered by Kobweb") } } } kotlin { configAsKobwebApplication("app") sourceSets { /* ... */ } }
plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.jetbrains.compose) alias(libs.plugins.kobweb.application) alias(libs.plugins.kobwebx.markdown) } kobweb { app { index { description.set("Powered by Kobweb") } } } kotlin { configAsKobwebApplication("app") sourceSets { /* ... */ } }
plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.jetbrains.compose) alias(libs.plugins.kobweb.application) alias(libs.plugins.kobwebx.markdown) } kobweb { app { index { description.set("Powered by Kobweb") } } } kotlin { configAsKobwebApplication("app") sourceSets { /* ... */ } }
# .kobweb/conf.yaml site: title: "App" server: port: 8080 files: dev: contentRoot: "build/processedResources/js/main/public" script: "build/dist/js/developmentExecutable/app.js" api: "build/libs/app.jar" prod: script: "build/dist/js/productionExecutable/app.js" siteRoot: ".kobweb/site"
# .kobweb/conf.yaml site: title: "App" server: port: 8080 files: dev: contentRoot: "build/processedResources/js/main/public" script: "build/dist/js/developmentExecutable/app.js" api: "build/libs/app.jar" prod: script: "build/dist/js/productionExecutable/app.js" siteRoot: ".kobweb/site"
# .kobweb/conf.yaml site: title: "App" server: port: 8080 files: dev: contentRoot: "build/processedResources/js/main/public" script: "build/dist/js/developmentExecutable/app.js" api: "build/libs/app.jar" prod: script: "build/dist/js/productionExecutable/app.js" siteRoot: ".kobweb/site"
<!-- example.html -->
<div
id="example"
style="width:50px;height:25px"
/>
Div(attrs = {
id("example")
style {
width(50.px)
height(25.px)
}
})
Div(attrs = { id("example") style { width(50.px) height(25.px) } })
Div(attrs = Modifier .attrsModifier { id("example") } .styleModifier { width(50.px) height(25.px) } .toAttrs() )
Div(attrs = Modifier .attrsModifier { id("example") } .styleModifier { width(50.px) height(25.px) } .toAttrs() )
Div(attrs = Modifier .attrsModifier { id("example") } .styleModifier { width(50.px) height(25.px) } .toAttrs() )
Div(attrs =
Modifier
.attrsModifier {
id("example")
}
.styleModifier {
width(50.px)
height(25.px)
}
.toAttrs()
)
Div(attrs = Modifier .id("example") .width(50.px) .height(25.px) .toAttrs() )
Div(attrs = Modifier .id("example") .width(50.px) .height(25.px) .toAttrs() )
// Kobweb
Div(attrs = Modifier
.id("example")
.width(50.px)
.height(25.px)
.toAttrs()
)
// Compose HTML
Div(attrs = {
id("example")
style {
width(50.px)
height(25.px)
}
})
Modifier
.padding(20.px)
.fillMaxWidth()
Modifier
.fillMaxWidth()
.padding(20.px)
Modifier
.padding(20.px)
.fillMaxWidth()
.padding(20.px)
Modifier
.padding(20.px)
.fillMaxWidth()
Modifier
.fillMaxWidth()
.padding(20.px)
Modifier
.padding(20.px)
.fillMaxWidth()
.padding(20.px)
// com/mysite/pages/About.kt package com.mysite.pages @Page @Composable fun AboutPage() { /* ... */ }
// com/mysite/pages/About.kt package com.mysite.pages @Page @Composable fun AboutPage() { /* ... */ }
// com/mysite/pages/Index.kt package com.mysite.pages @Page @Composable fun IndexPage() { /* ... */ }
// com/mysite/pages/DroidconSf.kt package com.mysite.pages @Page @Composable fun DroidconPage() { /* ... */ }
// com/mysite/pages/blog/_2024/DroidconSf.kt package com.mysite.pages.blog._2024 @Page @Composable fun DroidconPage() { /* ... */ }
// com/mysite/pages/patchNotes/Latest.kt package com.mysite.pages.patchNotes @Page @Composable fun LatestPage() { /* ... */ }
// com/mysite/acronyms/Html.kt package com.mysite.pages @Page("HTML") @Composable fun AboutPage() { /* ... */ }
// com/mysite/acronyms/Html.kt package com.mysite.pages @Page("HTML") @Composable fun AboutPage() { /* ... */ }
// com/mysite/pages/releases/_1_0_0/PackageMapping.kt @file:PackageMapping("1.0.0") package com.mysite.pages.releases._1_0_0 import com.varabyte.kobweb.core.PackageMapping
// com/mysite/pages/releases/_1_0_0/PackageMapping.kt @file:PackageMapping("1.0.0") package com.mysite.pages.releases._1_0_0 import com.varabyte.kobweb.core.PackageMapping
// com/mysite/pages/users/user/PackageMapping.kt @file:PackageMapping("{user}") package com.mysite.pages.users.user import com.varabyte.kobweb.core.PackageMapping
// com/mysite/pages/users/user/posts/Post.kt package com.mysite.pages.users.user.posts @Page("{post}") @Composable fun PostPage() { /* ... */ }
// com/mysite/pages/users/user/PackageMapping.kt @file:PackageMapping("{}") package com.mysite.pages.users.user import com.varabyte.kobweb.core.PackageMapping
// com/mysite/pages/users/user/posts/Post.kt package com.mysite.pages.users.user.posts @Page("{}") @Composable fun PostPage() { /* ... */ }
@Page @Composable fun IndexPage() { val ctx = rememberPageContext() /* ... */ }
@Page @Composable fun WatchPage() { val ctx = rememberPageContext() val videoId = ctx.route.params.getValue("v").toInt() /* ... */ }
@Page("{}") @Composable fun PostPage() { val ctx = rememberPageContext() val userName = ctx.route.params.getValue("user").toInt() val postId = ctx.route.params.getValue("post").toInt() /* ... */ }
import com.mysite.components.sections.NavHeader import com.mysite.components.sections.Footer @Composable fun PageLayout(content: @Composable () -> Unit) { Column { NavHeader() content() Footer() } }
import com.mysite.components.sections.NavHeader import com.mysite.components.sections.Footer @Composable fun PageLayout(content: @Composable () -> Unit) { Column { NavHeader() content() Footer() } }
import com.mysite.components.sections.NavHeader import com.mysite.components.sections.Footer @Composable fun PageLayout(content: @Composable () -> Unit) { Column { NavHeader() content() Footer() } }
import com.mysite.components.sections.NavHeader import com.mysite.components.sections.Footer @Composable fun PageLayout(content: @Composable () -> Unit) { Column { NavHeader() content() Footer() } }
import com.mysite.components.layouts.PageLayout @Page @Composable fun IndexPage() { PageLayout { /* ... */ } }
import com.mysite.components.layouts.PageLayout @Page @Composable fun IndexPage() { PageLayout { /* ... */ } }
Img( src = "/images/buster.jpg", attrs = Modifier.fillMaxSize() .toAttrs() )
Button(onClick = { /* ... */ }) {
Text("Click me")
}
var checked by remember { mutableStateOf(false) }
Checkbox(checked, onCheckedChange = { checked = it }) {
Text("Check me!")
}
Switch(checked, onCheckedChange = { checked = it })
var text by remember { mutableStateOf("") }
TextInput(
text,
placeholder = "type here",
onTextChanged = { text = it }
)
Div(modifier.backgroundColor(Colors.Cyan).toAttrs()) Tooltip(ElementTarget.PreviousSibling, "Hello!!!")
TextInput(variant = OutlinedInputVariant)
TextInput(variant = FilledInputVariant)
TextInput(variant = FlushedInputVariant)
TextInput(variant = UnstyledInputVariant)
val MyCustomInputVariant = InputStyle.addVariant {
/* ... */
}
/* example.css */ .rect { width: 50px; height: 25px; }
<!-- example.html --> <div id="example" class="rect" />
/* example.css */ .rect { width: 50px; height: 25px; }
<!-- example.html --> <div id="example" class="rect" />
Div(
Modifier
.id("example")
.width(50.px)
.height(25.px)
.toAttrs()
)
/* example.css */ .rect { width: 50px; height: 25px; }
<!-- example.html --> <div id="example" class="rect" />
val RectStyle = CssStyle { base { Modifier .width(50.px) .height(25.px) } }
Div( RectStyle.toModifier() .id("example") .toAttrs() )
/* example.css */ .rect { width: 50px; height: 25px; }
<!-- example.html --> <div id="example" class="rect" />
val RectStyle = CssStyle( extraModifier = Modifier.id("example") ) { base { Modifier .width(50.px) .height(25.px) } }
Div( RectStyle.toAttrs() )
val HoverStyle = CssStyle { base { Modifier .size(50.px) .backgroundColor(Colors.Cyan) } hover { Modifier.backgroundColor(Colors.Orange) } }
val HoverStyle = CssStyle { base { Modifier .size(50.px) .backgroundColor(Colors.Cyan) } hover { Modifier.backgroundColor(Colors.Orange) } }
val HoverStyle = CssStyle { base { Modifier .size(50.px) .backgroundColor(Colors.Cyan) } hover { Modifier.backgroundColor(Colors.Orange) } }
val HoverStyle = CssStyle { base { Modifier .size(50.px) .backgroundColor(Colors.Cyan) } hover { Modifier.backgroundColor(Colors.Orange) } }
val RectStyle = CssStyle { base { Modifier .width(50.px) .height(25.px) } }
val RectStyle = CssStyle { base { Modifier .width(50.px) .height(25.px) } }
val RectStyle = CssStyle { base { Modifier .width(50.px) .height(25.px) } }
val RectStyle = CssStyle.base { Modifier .width(50.px) .height(25.px) }
val SquareStyle = CssStyle.base { Modifier .size(50.px) .backgroundColor(Colors.Orange) } val RotatedSquareStyle = SquareStyle.extendedByBase { Modifier .rotate(45.deg) .backgroundColor(Colors.Cyan) }
val SquareStyle = CssStyle.base { Modifier .size(50.px) .backgroundColor(Colors.Orange) } val RotatedSquareStyle = SquareStyle.extendedByBase { Modifier .rotate(45.deg) .backgroundColor(Colors.Cyan) }
val SquareStyle = CssStyle.base { Modifier .size(50.px) .backgroundColor(Colors.Orange) } val RotatedSquareStyle = SquareStyle.extendedByBase { Modifier .rotate(45.deg) .backgroundColor(Colors.Cyan) }
val SquareStyle = CssStyle.base { Modifier .size(50.px) .backgroundColor(Colors.Orange) } val RotatedSquareStyle = SquareStyle.extendedByBase { Modifier .rotate(45.deg) .backgroundColor(Colors.Cyan) }
Box(SquareStyle.toModifier())
Box(RotatedSquareStyle.toModifier())
https://opletter.github.io/css2kobweb/
var colorMode by ColorMode.currentState Button( onClick = { colorMode = colorMode.opposite }, Modifier.borderRadius(50.percent).padding(0.px) ) { if (colorMode.isLight) FaSun() else FaMoon() }
var colorMode by ColorMode.currentState Button( onClick = { colorMode = colorMode.opposite }, Modifier.borderRadius(50.percent).padding(0.px) ) { if (colorMode.isLight) FaSun() else FaMoon() }
var colorMode by ColorMode.currentState Button( onClick = { colorMode = colorMode.opposite }, Modifier.borderRadius(50.percent).padding(0.px) ) { if (colorMode.isLight) FaSun() else FaMoon() }
val ColorBoxStyle = CssStyle.base { Modifier .size(50.px) .backgroundColor( if (colorMode.isDark) { Colors.Pink } else { Colors.DarkRed } ) }
val ColorBoxStyle = CssStyle.base { Modifier .size(50.px) .backgroundColor( if (colorMode.isDark) { Colors.Pink } else { Colors.DarkRed } ) }
val ColorBoxStyle = CssStyle.base { Modifier .size(50.px) .backgroundColor( if (colorMode.isDark) { Colors.Pink } else { Colors.DarkRed } ) }
val ResponsiveStyle = CssStyle { base { Modifier.backgroundColor(Colors.Red) } Breakpoint.SM { Modifier.backgroundColor(Colors.Yellow) } Breakpoint.MD { Modifier.backgroundColor(Colors.Green) } Breakpoint.LG { Modifier.backgroundColor(Colors.Blue) } }
val ResponsiveStyle = CssStyle { base { Modifier.backgroundColor(Colors.Red) } Breakpoint.SM { Modifier.backgroundColor(Colors.Yellow) } Breakpoint.MD { Modifier.backgroundColor(Colors.Green) } Breakpoint.LG { Modifier.backgroundColor(Colors.Blue) } }
val ResponsiveStyle = CssStyle { base { Modifier.backgroundColor(Colors.Red) } Breakpoint.SM { Modifier.backgroundColor(Colors.Yellow) } Breakpoint.MD { Modifier.backgroundColor(Colors.Green) } Breakpoint.LG { Modifier.backgroundColor(Colors.Blue) } }
val ResponsiveStyle = CssStyle { base { Modifier.backgroundColor(Colors.Red) } Breakpoint.SM { Modifier.backgroundColor(Colors.Yellow) } Breakpoint.MD { Modifier.backgroundColor(Colors.Green) } Breakpoint.LG { Modifier.backgroundColor(Colors.Blue) } }
val ResponsiveStyle = CssStyle { base { Modifier.backgroundColor(Colors.Red) } Breakpoint.SM { Modifier.backgroundColor(Colors.Yellow) } Breakpoint.MD { Modifier.backgroundColor(Colors.Green) } Breakpoint.LG { Modifier.backgroundColor(Colors.Blue) } }
val ResponsiveStyle = CssStyle { base { Modifier.backgroundColor(Colors.Red) } Breakpoint.SM { Modifier.backgroundColor(Colors.Yellow) } Breakpoint.MD { Modifier.backgroundColor(Colors.Green) } Breakpoint.LG { Modifier.backgroundColor(Colors.Blue) } }
val ResponsiveStyle = CssStyle { base { Modifier.backgroundColor(Colors.Red) } Breakpoint.SM { Modifier.backgroundColor(Colors.Yellow) } Breakpoint.MD { Modifier.backgroundColor(Colors.Green) } Breakpoint.LG { Modifier.backgroundColor(Colors.Blue) } }
// build.gradle.kts kotlin { sourceSets { jsMain.dependencies { implementation(libs.silk.icons.fa) } } }
FaEye()
FaHeart(style = IconStyle.FILLED)
Text("Kobweb")
Kobweb
// build.gradle.kts kotlin { sourceSets { jsMain.dependencies { implementation(libs.silk.icons.mdi) } } }
MdiVisibility(style = IconStyle.OUTLINED)
MdiFavorite()
Text("Kobweb")
visibility favorite Kobweb
// build.gradle.kts plugins { alias(libs.plugins.kobwebx.markdown) } kotlin { sourceSets { jsMain.dependencies { implementation(libs.kobwebx.markdown) } } }
<!-- resources/markdown/posts/kobweb.md -->
# Kobweb
[Kobweb](https://github.com/varabyte/kobweb) is built on
top of Compose HTML, an official reactive web UI framework
created by JetBrains.
// build/generated/pages/posts/Kobweb.kt
@Page
@Composable
fun KobwebPage() {
H1 { Text("Kobweb") }
/* ... */
}
---
root: .components.layout.ArticleLayout
author: BitSpittle
tags:
- Web Dev
- Tech
- Kotlin
---
@Composable fun ArticleLayout(content: @Composable () -> Unit) { val ctx = rememberPageContext() val markdown = ctx.markdown!! val author = markdown.frontMatter.getValue("author").single() val tags = markdown.frontMatter.getValue("tags") /* ... */ }
@Composable fun ArticleLayout(content: @Composable () -> Unit) { val ctx = rememberPageContext() val markdown = ctx.markdown!! val author = markdown.frontMatter.getValue("author").single() val tags = markdown.frontMatter.getValue("tags") /* ... */ }
@Composable fun ArticleLayout(content: @Composable () -> Unit) { val ctx = rememberPageContext() val markdown = ctx.markdown!! val author = markdown.frontMatter.getValue("author").single() val tags = markdown.frontMatter.getValue("tags") /* ... */ }
@Composable fun ArticleLayout(content: @Composable () -> Unit) { val ctx = rememberPageContext() val markdown = ctx.markdown!! val author = markdown.frontMatter.getValue("author").single() val tags = markdown.frontMatter.getValue("tags") /* ... */ }
Today is ${.component.widgets.CurrentDay}.
{{{ .component.widgets.Clock }}}
Today is ${.component.widgets.CurrentDay}.
{{{ .component.widgets.Clock }}}
Today is Jun 7, 2024.
--- imports: - .components.widgets.* --- Today is ${CurrentDay}. {{{ Clock }}}
--- imports: - .components.widgets.* --- Today is ${CurrentDay}. {{{ Clock }}}
Today is Jun 7, 2024.
// build.gradle.kts kotlin { configAsKobwebApplication( "app", includeServer = true ) sourceSets { jsMain.dependencies { /* ... */ } jvmMain.dependencies { compileOnly(libs.kobweb.api) /* ... */ } } }
// build.gradle.kts kotlin { configAsKobwebApplication( "app", includeServer = true ) sourceSets { jsMain.dependencies { /* ... */ } jvmMain.dependencies { compileOnly(libs.kobweb.api) /* ... */ } } }
// jvmMain/com/mysite/api/hello.kt
@Api
suspend fun hello(ctx: ApiContext) {
ctx.res.setBodyText("hello world")
}
// Backend
@Api
suspend fun hello(ctx: ApiContext) {
ctx.res.setBodyText("hello world")
}
// Frontend @Page @Composable fun FullstackPage() { var fetchedText by remember { mutableStateOf("") } LaunchedEffect(Unit) { fetchedText = window.api.get("hello") .decodeToString() } Text(fetchedText) }
// Frontend @Page @Composable fun FullstackPage() { var fetchedText by remember { mutableStateOf("") } LaunchedEffect(Unit) { fetchedText = window.api.get("hello") .decodeToString() } Text(fetchedText) }
// Frontend @Page @Composable fun FullstackPage() { var fetchedText by remember { mutableStateOf("") } LaunchedEffect(Unit) { fetchedText = window.api.get("hello") .decodeToString() } Text(fetchedText) }
// Backend
@Api
suspend fun hello(ctx: ApiContext) {
if (ctx.req.method != HttpMethod.GET) return
// NOTE: Sets `ctx.res.status = 200`
ctx.res.setBodyText("hello world")
}
// Backend @Api suspend fun contactMe(ctx: ApiContext) { if (ctx.req.method != HttpMethod.POST) return // 1: Read data from request // 2: Write message into a data store ctx.res.status = 200 }
// Backend @Api suspend fun contactMe(ctx: ApiContext) { if (ctx.req.method != HttpMethod.POST) return // 1: Read data from request // 2: Write message into a data store ctx.res.status = 200 }
// Backend @Api suspend fun contactMe(ctx: ApiContext) { if (ctx.req.method != HttpMethod.POST) return // 1: Read data from request // 2: Write message into a data store ctx.res.status = 200 }
// build.gradle.kts plugins { alias(libs.plugins.kotlin.serialization) } kotlin { sourceSets { commonMain.dependencies { implementation(libs.kotlinx.serialization.json) } } }
// Backend
@Api
suspend fun contactMe(ctx: ApiContext) {
// 1: Read data from request
}
// Common
@Serializable
class ContactMeMessage(
val firstName: String,
val lastName: String,
val subject: String,
val message: String,
)
// Common
@Serializable
class ContactMeMessage(
val firstName: String,
val lastName: String,
val subject: String,
val message: String,
)
// Backend @Api suspend fun contactMe(ctx: ApiContext) { val msg: ContactMeMessage = Json.decodeFromString( ctx.req.body!!.decodeToString() ) }
// Backend @Api suspend fun contactMe(ctx: ApiContext) { val msg: ContactMeMessage = Json.decodeFromString( ctx.req.body!!.decodeToString() ) }
// Backend @Api suspend fun contactMe(ctx: ApiContext) { val msg: ContactMeMessage = Json.decodeFromString( ctx.req.body!!.decodeToString() ) }
// Backend
@Api
suspend fun contactMe(ctx: ApiContext) {
// 2: Write message into a data store
}
// Backend interface DataStore { fun addText(id: String, text: String) } @InitApi fun initApi(ctx: InitApiContext) { ctx.data.add<DataStore>(DataStoreImpl()) }
// Backend interface DataStore { fun addText(id: String, text: String) } @InitApi fun initApi(ctx: InitApiContext) { ctx.data.add<DataStore>(DataStoreImpl()) }
// Backend interface DataStore { fun addText(id: String, text: String) } @InitApi fun initApi(ctx: InitApiContext) { ctx.data.add<DataStore>(DataStoreImpl()) }
// Backend @Api suspend fun contactMe(ctx: ApiContext) { val msg: ContactMeMessage ctx.data.getValue<DataStore>().addText( id = "${msg.lastName}, ${msg.firstName}", text = "${msg.subject}: ${msg.message}" ) }
// Backend @Api fun contactMe(ctx: ApiContext) { if (ctx.req.method != HttpMethod.POST) return val msg: ContactMeMessage = Json.decodeFromString( ctx.req.body!!.decodeToString() ) ctx.data.getValue<DataStore>().addText( id = "${msg.lastName}, ${msg.firstName}", text = "${msg.subject}: ${msg.message}" ) ctx.res.status = 200 }
// Backend @Api fun contactMe(ctx: ApiContext) { if (ctx.req.method != HttpMethod.POST) return val msg: ContactMeMessage = Json.decodeFromString( ctx.req.body!!.decodeToString() ) ctx.data.getValue<DataStore>().addText( id = "${msg.lastName}, ${msg.firstName}", text = "${msg.subject}: ${msg.message}" ) ctx.res.status = 200 }
// Backend @Api fun contactMe(ctx: ApiContext) { if (ctx.req.method != HttpMethod.POST) return val msg: ContactMeMessage = Json.decodeFromString( ctx.req.body!!.decodeToString() ) ctx.data.getValue<DataStore>().addText( id = "${msg.lastName}, ${msg.firstName}", text = "${msg.subject}: ${msg.message}" ) ctx.res.status = 200 }
// Backend @Api fun contactMe(ctx: ApiContext) { if (ctx.req.method != HttpMethod.POST) return val msg: ContactMeMessage = Json.decodeFromString( ctx.req.body!!.decodeToString() ) ctx.data.getValue<DataStore>().addText( id = "${msg.lastName}, ${msg.firstName}", text = "${msg.subject}: ${msg.message}" ) ctx.res.status = 200 }
// Frontend val scope = rememberCoroutineScope() Button(onClick = { val msg = ContactMeMessage( firstName, lastName, subject, message ) scope.launch { window.api.post( "contact-me", body = Json.encodeToString(msg) .encodeToByteArray() ) } }) { Text("Send Message") }
// Frontend val scope = rememberCoroutineScope() Button(onClick = { val msg = ContactMeMessage( firstName, lastName, subject, message ) scope.launch { window.api.post( "contact-me", body = Json.encodeToString(msg) .encodeToByteArray() ) } }) { Text("Send Message") }
// Frontend val scope = rememberCoroutineScope() Button(onClick = { val msg = ContactMeMessage( firstName, lastName, subject, message ) scope.launch { window.api.post( "contact-me", body = Json.encodeToString(msg) .encodeToByteArray() ) } }) { Text("Send Message") }
// Frontend val scope = rememberCoroutineScope() Button(onClick = { val msg = ContactMeMessage( firstName, lastName, subject, message ) scope.launch { window.api.post( "contact-me", body = Json.encodeToString(msg) .encodeToByteArray() ) } }) { Text("Send Message") }
Modifier
AppGlobals
deferRender
kobweb { ... }
configurationconf.yaml
configuration