elide (v3)

elide: verb. to omit (a sound or syllable) when speaking. to join together; to merge.


Reliability Rating Security Rating Maintainability Rating

Kotlin ECMA GraalVM Micronaut React

Elide is under construction. You can also browse to v2 or v1.


What do you mean by meta-framework?

Elide could be characterized as a meta-framework in the sense that it is powered entirely by mature and well-supported software under the hood. Via a thin combination of build tooling and runtime interfaces, the developer can leverage these tools together without worrying about performance or compatibility.

Cross-platform features

  • Primitives. Access the entire Kotlin Standard Library, with additional sugar added, and the full suite of KotlinX extensions including serialization, atomicfu, coroutines, and datetime.

  • Logging. Use an identical interface across platforms, which calls into the best layer available for that system. For example, on the JVM, logging calls into slf4j, and in JavaScript, console.*.

  • Observability. Generate uniform logs across platforms, which correlate and provide a fully observable picture of application behavior.

  • Data modeling. Express data models once, with support for databasing, serialization/de-serialization, and data exchange via RESTful APIs, gRPC, or gRPC-Web.

Distinguishing features

  • Native development with Kotlin. Write your core application logic and models once, and share them across platforms transparently. Leverage Kotest for cross-platform, write-once-run-native testing.

  • Isomorphic SSR with React. Write your UI in React, using JavaScript, TypeScript, or Kotlin. Package it for serving via client-side rendering or hybrid isomorphic rendering directly from your Kotlin server.

  • Model-driven development. Write your models once, and use them everywhere, across platforms, without copying, without glue-code, and without DTOs. Via Protobuf and Kotlin data classes, the same Elide model is code-generated for use with your database, API, and UI.

Code samples

A full suite of code samples demo various functionality. The samples are runnable locally or via pre-built Docker images. Click through to each one for a short tour and getting started guide.

“Blah blah blah, okay, show me some code.” Certainly:

App.kt (for the server)

/** GET `/`: Controller for index page. */
@Controller class Index {
  // Serve an HTML page with isomorphic React SSR.
  @Get("/") fun index() = ssr {
    head {
      title { +"Hello, Elide!" }
      stylesheet("/styles/main.css")
      script("/scripts/ui.js", defer = true)
    }
    body {
      injectSSR()
    }
  }

  // Serve styles for the page.
  @Get("/styles/main.css") fun styles() = css {
    rule("body") {
      backgroundColor = Color("#bada55")
    }
    rule("strong") {
      fontFamily = "-apple-system, BlinkMacSystemFont, sans-serif"
    }
  }

  // Serve the built & embedded JavaScript.
  @Get("/scripts/ui.js") fun js() = asset(
    "frontend.js",
    "js",
    MediaType("application/javascript", "js"),
  )
}

main.kt (for the browser)

// React props for a component
external interface HelloProps: Props {
  var name: String
}

// React component which says hello
val HelloApp = FC<HelloProps> { props ->
  div {
    strong {
      +props.name
    }
  }
}

// Entrypoint for the browser
fun main() {
  hydrateRoot(
    document.getElementById("root"),
    Fragment.create() {
      HelloApp {
        name = "Elide"
      }
    }
  )
}

That’s it. That’s the entire app. In fact, it’s just the fullstack/react-ssr sample pasted into the README. What we get out of this is surprising:

  • Server: JVM or Native server (via GraalVM) that serves our root page, our CSS, and our JS
  • Client: Embedded JS VM that executes a Node copy of our React UI and splices it into the page for isomorphic rendering
  • For us (the developer):
    • Completely type-checked calls across platforms, with almost no boilerplate
    • Single build graph, with aggressive caching and tool support
    • Build & test virtualized on any platform
    • Ship & perform natively on any platform

What’s going on here? Elide has helped us wire together code from Micronaut (that’s where @Controller comes from), Kotlin/JS, GraalVM, and esbuild to make the above code make sense on both platforms. The React code builds for the browser and a pure server environment; both are embedded into the JAR and served through a thin runtime layer provided by the framework.

Why is this useful?

If you’re participating in the React and Java ecosystems, this gives you a fantastic best-of-both-worlds runtime option: superb tooling support for React and Kotlin and an ideal serving and rendering mode, all handled for you.

You can do the same thing with these same tools in a custom codebase, but setting up the build environment for this kind of app is challenging and error-prone. Elide intentionally leverages existing frameworks with rich ecosystems and docs, instead of re-providing existing functionality so that you always have an escape hatch up to a more industrial toolset if you need it.

Trying it out

Note Elide is early. This guide will soon be usable without cloning the source.

There are currently two ways to try out Elide. You can build a sample from source, or run the pre-built Docker images. Native images are not yet available via Docker, but you can build and test them locally.

The react-ssr sample is recommended, because it demoes the broadest set of functionality currently available. Source code for each sample is in the samples/ directory. If you’re going to build from source, make sure to see the Requirements to build section.

Run the helloworld sample via Docker (JVM):

docker run --rm -it -p 8080:8080 ghcr.io/elide-dev/samples-server-helloworld-jvm

Run the react-ssr sample via Docker (JVM):

docker run --rm -it -p 8080:8080 ghcr.io/elide-dev/samples-fullstack-react-ssr-jvm:latest

Run the react-ssr sample via Gradle (JVM):

git clone [email protected]:elide-dev/v3.git && cd v3
./gradlew :samples:fullstack:react-ssr:server:run

Run the react-ssr sample via Gradle (Native):

git clone [email protected]:elide-dev/v3.git && cd v3
./gradlew :samples:fullstack:react-ssr:server:runNative

Requirements to build

To build the JVM or JS samples in Kotlin, you will need JDK 11 or later. Zulu is a good option if you don’t have a preferred JVM.

To build native code, you’ll need a recent version of GraalVM. Make sure to install the native-image tool after initially downloading, which you can do with:

gu install native-image espresso
gu rebuild-images

Finally, you’ll need a recent Node.js runtime if you want to build JS or frontend code. That’s it!

To summarize:

  • For building via Gradle: JDK11+, any reasonable JVM should work.
  • For building native: GraalVM (consult compat table for version advice).
  • For building browser/embedded JS: Recent Node.js toolchain. 16.x+ is recommended.

Powered-by

Elide is modular. You can mix and match the following technologies in server, client, or hybrid/fullstack development scenarios:

  • Kotlin. Elide is written from the inside out with support for Kotlin/Multiplatform, including native platforms. Write once and use the same consistent code across server-side and client-side(s) platforms.

  • GraalVM. GraalVM is a JVM and toolchain from Oracle which includes modernized JIT support, cross-language polyglot development in JS, Ruby, Python, and LLVM, and the ability to build native binaries from JVM apps.

  • Micronaut. Micronaut is a new JVM-based framework for building server-side applications. Elide leverages Micronaut’s dependency injection and AOP features, and transparently works with most add-ons.

  • React. React is a popular UI library written for browser and server environments. Elide leverages Kotlin/JS support for React for isomorphic UI rendering. CSR and SSR modes are supported natively.

  • Protobuf / gRPC. Elide leverages cross-platform serialization through KotlinX’s protobuf module, and includes native support for gRPC Web without running a proxy.

  • Closure. Use the Closure Tools family of software to develop performant and low-level JavaScript apps that are served directly from your application JAR. Render Soy templates server-side with Google’s blazing-fast Soy Sauce runtime, via pre-compiling templates to Java bytecode.

  • Bazel. Built-in support for Bazel. Load directly from a tarball; build only what you use. Extensive suite of utility macros and rules.

  • Gradle. Early support for building multi-platform Kotlin applications via Gradle, including integrated support for Webpack-based frontend builds and esbuild-based embedded SSR builds.

Version compatibility

The following version matrix indicates tested support across tool and platform versions, including Java, Kotlin, GraalVM, Micronaut, and React.

Following this guide is recommended but optional. Depending on the style of development you’re doing with Elide, you may not need some of these components:

Status Java Kotlin GraalVM Micronaut React Protobuf/gRPC
Status Java 17 1.7.0 22.1.x 3.5.x 18.x 3.20.1/1.46.0
Status Java 11 1.7.0 22.1.x 3.5.x 18.x 3.20.1/1.46.0
Status Java 8

If you aren’t using certain components on this list, for example, gRPC/Protobuf, you can ignore that column entirely.

Platform Support

Elide itself generally supports any platform supported by GraalVM. This includes Linux, macOS, and Windows. Client-side, all major browsers are supported, along with Android and iOS via Kotlin/Native.

Please consult the table below for a complete list of supported platforms and architectures:

Build OS Arch Libc Supported Notes
Build Linux (Ubuntu) x86_64 libc Default JVM platform
Build macOS x86_64 libc Supported dev platform
Build macOS arm64 libc Supported dev platform
Build Linux (Alpine) x86_64 musl ☢️ Experimental
Build Linux (Ubuntu) arm64 libc ☢️ Experimental
Build Windows x86_64 N/A ☢️ Experimental

Bazel, Gradle, GraalVM, and Kotlin/Native must support a given platform for Elide to work across architectures.

“What about [x] functionality that I want/need?”

Java, and, by extension, Kotlin, has one of the broadest and most active software ecosystems on the planet, closely followed by NodeJS, via NPM.

Elide supports both and allows you to access software written for both. Here are some examples to get you going.

About this framework

Elide has existed in different forms for over a decade. It was first released under the name canteen in 2011 as a Python package. Later, the code evolved into Bazel/Java, then Bazel/Kotlin, and now Bazel/Gradle/Kotlin.

These frameworks were distinct from each other, written for a moment in time, but they shared authors, design patterns, and goals:

  • The developer should have to write as little code as possible without resorting to convention. Elide, in this way, is partly a reaction to the drawbacks of Rails-style architectures (and Next.js, which came much later).

  • If it builds, it should work. As much as possible, type checking and code-gen should be leveraged where a human developer adds little or no value. Aligning types is a detailed and error-prone process, which is well suited for a computer.

  • A thing is just a thing. Not what is said of that thing. Data is the effective king of runtime. An application’s concepts should be strongly expressed as models, and the developer should not have to repeat themselves across platforms to actualize or interchange expressions of those concepts.

History

Adopters

Collectively, over a span of 10+ years, Elide has served millions of requests per month on behalf of the following organizations (newest first):

  • Cookies. Elide powered all customer-facing digital properties, including the main Cookies site and e-commerce experience, with traffic reaching millions of users and unique hits per month.

  • Bloombox. Elide powered the APIs underlying Bloombox’s B2B retail application, scaling to millions of requests per month.

  • Ampush. Elide powered internal ad-tech systems at Ampush, which reached millions of events and requests per day.

  • Keen IO. Elide powered the Keen website for a time, which reached millions of developers across the span of its early use in Python.

Timeline

  • [2012] canteen: Leveraged Python meta-classes and cooperative greenlets after the release of gevent. “Holds more water than a flask.” Inspired heavily by tipfy. Created at Keen IO and adopted to run production systems at Ampush Media.

  • [2015]: gust: Written to integrate Kotlin with Bazel, ultimately with support for Soy, J2CL, Protobuf, and the Closure ecosystem of tools (via rules_closure, shout out to @jart!). Powered production systems at Momentum Ideas and Bloombox.

  • [2020]: gust (elide v1): Rewritten in Java/Kotlin, with native support for Bazel, to continue gust‘s evolution for production use at Cookies.

  • [2021]: elide v2: New model layer support with the addition of Redis, Firestore, and Spanner, to support the launch of Cookies‘ integrated e-commerce experience.

  • [2022-now]: elide v3: Complete rewrite into pure Kotlin to leverage Kotlin Multiplatform, with native support for polyglot development via GraalVM, gRPC/Protobuf, and React. Build tooling support through Bazel and Gradle.

GitHub

View Github