Skip to content
Lucent
SEARCH LUCENT

Search guides, APIs, and examples.

GitHub

Very early and experimental. The language, the generated native code and every package API change without notice. Do not use Lucent in production.

Your first module

In ten minutes: write a module, call it from a screen, change it, and read a compile error.

  1. greet.lucent.ts
    export function greet(name: string): string {
    const trimmed = name.trim();
    return trimmed.length > 0 ? `Hello, ${trimmed}!` : "Hello, stranger!";
    }
    See the C++
    m_greet.cpp
    // Generated by Lucent from greet.lucent.ts. Do not edit.
    #include "m_greet.h"
    #pragma push_macro("greet")
    #undef greet
    #pragma push_macro("trimmed")
    #undef trimmed
    namespace lucent_app {
    lucent::String m_greet::greet(lucent::String p0_) {
    #line 2 "greet.lucent.ts"
    lucent::String trimmed = p0_.trim();
    #line 3 "greet.lucent.ts"
    double v3_ = static_cast<double>(trimmed.length());
    bool v5_ = v3_ > 0.0;
    lucent::String v12_{};
    if (v5_) {
    v12_ = lucent::String(lucent::String(LUCENT_STR("Hello, ")) + trimmed) + LUCENT_STR("!");
    } else {
    v12_ = LUCENT_STR("Hello, stranger!");
    }
    #line 3 "greet.lucent.ts"
    return v12_;
    }
    void m_greet::init() {
    }
    } // namespace lucent_app
    #pragma pop_macro("trimmed")
    #pragma pop_macro("greet")

    Save it as src/greet.lucent.ts. Any *.lucent.ts file is a module, and its exports are what JavaScript can call.

  2. App.tsx
    import { Text } from "react-native";
    import { greet } from "./src/greet.lucent";
    export default function App() {
    return <Text>{greet(" Ada ")}</Text>;
    }

    The import is typed from the source, so your editor checks the call.

  3. terminal
    npx expo run:ios

    The config plugin builds your modules during prebuild. Xcode then compiles the C++ into the app.

    The screen shows Hello, Ada!, computed in C++.

  4. Change Hello to Hi and save. While Metro runs, lucent dev rebuilds the native package and prints one line in Metro's output:

    terminal
    [14:02:11] ✓ 2 modules 36 ms · rebuild the app

    The C++ is part of the app binary, so reloading JavaScript doesn't replace it. Run the app again to see Hi, Ada!.

  5. Change the parameter to name: any and save:

    terminal
    [14:03:40] ✗ 1 error
    src/greet.lucent.ts:1:23 LUCENT2001 `any` has no native representation; give this value a concrete type
    fix: use a concrete type, a union, or a generic parameter

    Each error has a code, a place and a fix. npx lucent explain LUCENT2001 shows why the rule exists, with a wrong and a right example. Put string back.

  1. The TypeScript checker checked greet.lucent.ts against Lucent's rules.
  2. Lucent compiled it to C++ and wrote the native package to .lucent/native.
  3. Xcode or Gradle compiled the native package into your app.
  4. Metro replaced the greet.lucent import with a proxy.
  5. Calling greet went through JSI to the C++ and back.

How Lucent works follows each step.