varabyte / kobweb Goto Github PK
View Code? Open in Web Editor NEWA modern framework for full stack web apps in Kotlin, built upon Compose HTML
Home Page: https://kobweb.varabyte.com
License: Apache License 2.0
A modern framework for full stack web apps in Kotlin, built upon Compose HTML
Home Page: https://kobweb.varabyte.com
License: Apache License 2.0
JGit is... fine, but 1) it diverges from real git sometimes and 2) it doesn't support clone --depth 1, which is a real disappointment.
We can use JGit if git can't be found, but otherwise, let's use real git instead. As a side bonus for using real git, we can offer to init and create an initial commit.
Right now, it's not too hard to make the generated code with "useSilk = true" crash, e.g. This is a line with a [link](http://www.google.com) in it
Let's audit all the features (including inline source code and indented source code) and make sure they all work.
(once konsole supports offscreen rendering)
kobweb run --gradle "--stacktrace --debug"
maybe?
Short version: It's possible my Gradle fu is not good. I needed a way to run a task that starts a server but then doesn't run forever (so, e.g., I could run the server and then call kobwebBuild next).
Also, my custom server supports better feedback for livereloading vs. webpack which does not (as far as I can tell)
Despite being empty, it should ask you if you want to support Silk and Markdown
We should look at how Jetpack Compose does it with Material theming and also Chakra UI?
I found out about this annotation after starting, so while I've added it in some places, I'm not sure if I've added it everywhere
This would be something where the type is in commonMain
(or some third party multiplatform module) and both client and servers could use it. This could be an interesting thing to do with demonstrating serverless functions, that is instead of just returning a String, return a type converted to JSON or something.
I have already started some work on this but I need to take it across the finish line.
For reference we want to allow something like this but the Kotlin way: https://chakra-ui.com/docs/theming/component-style
Probably a spinner, maybe showing a Kobweb or the Varabyte logo
Right now we're always generating the link to font awesome icons, which might be expensive if you have an app that isn't using them.
Instead, there should be a way for the user to indicate they don't want it. Maybe just a kobweb.conf.yaml setting? Or we can figure it out if they don't have a dependency on the font awesome icon kobweb artifact?
Currently, we're using replaceState in Router.kt. But if we use pushState instead of replaceState, it kind of works but we
aren't notified when the back or forward event happens. This shouldn't be too hard once we learn how to listen to URL change events.
See also:
https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
https://www.freecodecamp.org/news/how-to-detect-a-users-preferred-color-scheme-in-javascript-ec8ee514f1ef/ (css query: prefers-color-scheme
)
This will complete with the one we will autogenerate. So they shouldn't do that!
So not just {{ .components.SomeCall }}
but also maybe
{{ .components.SomeCall(...)
This is text content that will get nested under the call.
}}
which would generate code like:
org.example.myproject.components.SomeCall(...) {
Text("This is text content...")
}
See also: google/ksp#33
For now, maybe just hack things by parsing "manually" with like a regex or something?
To check off items on this list, they should both be supported AND documented
These items probably just need files to be exported a certain way
These items probably need logic currently backed into the kobweb/backend
codebase refactored out into a shareable JVM library and then implemented per target
I'm not familar with these technologies at this point so they will require a bit more investigation to categorize / understand properly
Original comment:
Feedback from the community: "end to end does provide a better headstart experience. but afaik backend is super complex so integrating it w/ something like spring boot would make it a lot more feasible for many use cases"
When I created the initial project, I selected a bunch of plugins that seemed relevant, but right now they may not be being used, and some of them are generating compiler warnings.
Perhaps something like this:
@Page
@Composable
fun HomePage() {
var colorMode by rememberColorMode()
SilkTheme {
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Row(Modifier.fillMaxWidth().height(20.dp)) {
Spacer()
Button(
onClick = { colorMode = colorMode.opposite() },
) {
when (colorMode) {
ColorMode.LIGHT -> FaSun()
ColorMode.DARK -> FaMoon()
}
}
}
H1 {
Text("Welcome to Kobweb!")
}
Row {
Text("Create rich, dynamic web apps with ease, leveraging ")
Link("https://kotlinlang.org/", "Kotlin")
Text(" and ")
Link("https://compose-web.ui.pages.jetbrains.team/", "Web Compose")
}
}
}
}
Perhaps an option to the @Page()
annotation? Or maybe an annotation on its own so you can configure rules that match against a large area, like "don't export anything under the 'pages.admin'" package or something
@Api
fun someRoute(ctx) {
// Do nothing
}
right now, this sends an empty "200" response, the idea being that the user defined the endpoint, so that's enough. But I'm not sure if that's intuitive, or if instead we should require the user do something:
@Api
fun someRoute(ctx) {
ctx.res.status = 200 // body automatically set to "" if not already set
}
or
@Api
fun someRoute(ctx) {
ctx.res.body = "..." // status automatically set to 200 if not already set
}
This way, we can write code like:
@Api
fun someRoute(ctx) {
if (ctx.req.method == GET) {
ctx.res.body = ...
}
}
and other methods will return a 400
Probably we need to query window.history to see if we already visited the link before.
It throws an exception around Gradle not working because it should be using "gradlew.bat" instead.
Still, calling gradlew.bat kobwebStart
manually is also not working. It says that a folder (.kobweb
) isn't found even though it's totally there. Maybe Windows hides dot folders by default or something? This needs investigation.
For now, because it's easier to get up and running, version checking and status message code lives in MainTemplate.kt. Instead, it should be done by the server and not leak to users.
By not baking the logic in the templates, it also means we can be more flexible about server behavior in the future; maybe we'll significantly want to change what our live reloading stuff looks like
If I call a markdown component inside my md file:
---
key: value
---
Here is a cool demo:
[.components.tutorial5.PathFindingCanvas]
Thanks for reading
then if I define my canvas like so:
@Composable
fun PathFindingCanvas(data: Map<String, List<String>>) {
...
}
we should pass in the data automatically. (Maybe there should be an MdData type alias?)
Alternately, maybe it should be a special "MdContext" class?
class MdContext {
val frontMatter: Map<String, List<String>>
val data: MutableMap<String, Any>
}
which will be easier to extend later, and that way components within the same page can share data with each other....
Links, due to privacy issues, don't let the developer know if they're visited or not. That means we HAVE to use the global css approach, as in a:visited { ... }
.
The problem is, we want to change the link color when color mode changes. I think we can do that using css variables, but I'm not 100% sure.
Misc
Web Compose investigation
Kobweb (Binary)
google-chrome --headless --disable-gpu --dump-dom http://localhost:8080/
Kobweb (Core)
${SomeComponent()}
Kobweb Silk
Site
Instead, use -P to pass a property for the environment so we can reduce the number of tasks
Or is this already provided by web compose?
Something like
Press SPACE to (pause|resume) live reloading.
Question to mull over -- should we keep letting Gradle do its thing but just tell the web server to ignore it? Or should we actually stop Gradle temporarily and then rerun it?
Let's try the "stop Gradle" one but if that doesn't work, web server as a fallback?
I need to think through this feature. Do we even want to allow it? Will it allow us to specify dynamic routes, e.g. https://nextjs.org/docs/routing/dynamic-routes ?
If we do support it, we need to update the Kobweb gradle plugin to detect the slug name inside the annotation and use it instead of the file name.
If a user creates a very very very large site, is there a way we can structure a project, maybe into multiple modules, to avoid having one gigantic js file?
This is inspired by next.js, which does some sort of smart breaking up of logic.
Example errors to log:
Instead, it should be instantiated in main and then exposed to children who care via a provider.
Right now we aren't too careful about people reading and writing to server/state.yaml and requests.yaml, but in the future we should do a better job protecting against multiple writes.
We can possibly use a RandomAccessFile / in memory file here, with exclusive access?
See also: JetBrains/compose-multiplatform#1333
Currently, it seems like generics in composables are causing the compose compiler to trip up, so I'm simplifying the ComponentStyles API for now. However, this requires passing in a data: Any?
parameter, which is ugly.
Revisit this if / when the upstream bug is resolved.
Compare:
# web compose
interface DisplayStyle: StylePropertyEnum {
companion object {
inline val Block get() = DisplayStyle("block")
inline val Inline get() = DisplayStyle("inline")
...
inline val Initial get() = DisplayStyle("initial")
inline val Unset get() = DisplayStyle("unset")
}
}
# kobweb compose
enum class FontStyle(val value: String) {
NORMAL("normal"),
ITALIC("italic"),
}
We should match upstream style, especially we hope someday that maybe they'll implement the holes we're filling
For now we're always using "helloworld", but we should instead get this from the user's project name. Perhaps if the user's package is "com.example.myproject", we should just set it to "myproject"?
Right now, there's no way to get a breakpoint on the server. It would be nice if we could figure that out, but at the very least, we should support logging via the ApiContext in some way.
We can use this to show that the build failed so the page won't reload
This should crawl a repository and return the list of all found templates, sorted? Maybe something like:
$ kobweb list
examples/todo - A functional TODO app
site - A minimal example site new users can start from
site/empty - A site that hooks up the bare minimum to get users started
Sometimes a server is left running and you don't want to kill it directly.
So just add Kobweb stop, which doesn't even need to run Gradle? It can just add a server request to the request.yaml file and while loop / sleep until it is deleted.
Something like:
---
author: bitspittle
---
This blog post was brought to you by {{ author }}
We'll need to think about this. This will really only work well if we think of this as a larger feature, e.g. you can specify a yaml config elsewhere with all variables and then reference them in a {{ }} block, like above maybe author
is set to nobody
by default unless specifically tagged in the front matter.
Then the question is, will we be able to reference those variables in the normal kt files as well???
The project parsing (KobwebProject.parseData) code probably makes sense to be Gradle only since only Gradle knows the "pages" and "group" values. Then we can remove the embeddedcompiler dependency from the CLI.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.