Giter Site home page Giter Site logo

varabyte / kobweb Goto Github PK

View Code? Open in Web Editor NEW
1.3K 19.0 58.0 5.57 MB

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

Kotlin 100.00%
compose web kotlin compose-html

kobweb's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kobweb's Issues

kobweb create, use real git if possible

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.

Set Markdown.useSilk to true by default

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.

Document why "kobwebStart" vs "jsRun"

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)

Demonstrate an example of sharing the file type on client and server

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.

Kobweb Plugin: Have a way to not generate unecessary header tags in index.html

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?

Support history (back and forward)

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.

Support multi-line kobweb calls in markdown

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...")
}

Epic: Allow Kobweb to work in cases where it doesn't own the server

To check off items on this list, they should both be supported AND documented

Static support

These items probably just need files to be exported a certain way

  • GCP
  • Netlify

Dynamic support

These items probably need logic currently backed into the kobweb/backend codebase refactored out into a shareable JVM library and then implemented per target

  • ktor
  • Spring Boot

Other

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"

Audit ktor plugins

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.

Change README hero sample to include color mode (and animated gif)

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")
            }
        }
    }
}

Add a way to disable exporting conditionally

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

Audit how API routes work when users don't explicitly do anything

@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

Windows doesn't work when you use `kobweb run`

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.

Move Kobweb hook code into the server

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

Pass "Map<String, List<String>>" to all markdown components if relevant

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....

Add Silk support for link colors

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.

MVP / Prototype TODOs

Misc

  • Figure out how to use markdown task lists
  • Finalize the name
  • Add a README with basic instructions

Web Compose investigation

  • Create a project where a multiplatform JS library with composables is consumed by a JS application
  • Figure out how to get hot reload to work automatically. (Answer: ./gradlew jsRun --continuous, plus lots of interesting options in https://kotlinlang.org/docs/js-ir-compiler.html)
  • Do we lean into the CSS approach as embraced by Web Compose, or try to mimic Jetpack Compose? Need to experiment with what it means to make a regular app and a website with kobweb.
  • Figure out how to discover all classes that subclass another class (e.g. HomePage which inherits from Page). This may need to be magically done by kobweb, maybe with KotlinPoet?
  • Will compile times be a major issue? (They're not great, but they're not the end of the world. ~1-2 seconds)

Kobweb (Binary)

  • Set up arg parser
  • Figure out how to get hot reload to work automatically.
  • Add support for "kobweb create --site --use-markdown" when run inside an empty folder
  • Figure out how to strip out classes from the final binary, to reduce the final html JS
  • Add support for "kobweb run --dev" when run inside a kobweb project
  • Add support for "kobweb build" which should generate a static site -- Note: this can be done by running chrome in headless, e.g. google-chrome --headless --disable-gpu --dump-dom http://localhost:8080/

Kobweb (Core)

  • Create App and Page classes, use them in a project
  • Use @page annotation instead of Page base class?
  • Handle routing using navigation + show in URL bar (Refresh should keep you on the active page)
  • Get markdown plugin working
  • API routes with shared types (e.g. "api/hello" defined in jvmMain returns a HelloMsg defined in commonMain and read by a page defined in jsMain)
  • Audit all markdown nodes (e.g. code blocks)
  • PageContext via provider, available in pages, includes "params: Map<String, String>" for now, and a home for markdown data if relevant
  • Allow markdown to reference code ${SomeComponent()}

Kobweb Silk

  • Figure out UI theming
  • Figure out dynamic color mode
  • Add Flex component
  • Add Link component
  • Can we avoid creating a Link class in kobweb.silk if we use css variables instead?
  • Shapes
  • Add icon support (React Icons?)
  • Add a canvas widget
  • #53
  • Breakpoints

Site

  • Create an explicit site runner for now (will eventually be handled by kobweb)
  • Create a hello world app that autoloads when user changes code
  • Create a hello world app with two pages that can link to each other ("/" and "/about")
  • Move site runner logic into kobweb
  • Create a sample app

"kobweb run" should allow the user to toggle live reloading

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?

Figure out how to break javascript up into several libraries

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.

Make nekt.compose.css enums consistent with WebCompose style

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

Add logging support for the server

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.

Add "kobweb list" command

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

Add kobweb stop

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.

Add a way to reference variables declared inside markdown front matter

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???

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.