OsmosJS Documentation

website·Indexed 29 days ago

https://osmosjs.com/docs/osmos

A lightweight, framework-agnostic, and customizable JSX runtime. Includes Osmosis for building documentation websites and integration with AdonisJS for application development, featuring components, context, and custom renderers.

Tokens
6.3K
Snippets
46
Records
54
Agent score
49%

What's inside OsmosJS

  1. Overview of Osmos JSX Runtime

    Osmos is a lightweight, framework-agnostic, server-only JSX runtime used to generate HTML on the server. Unlike client-first libraries like React, Osmos does not require a build step and is designed to eliminate the need for a full client-side API by generating the frontend entirely on the server. Key features include support for Async components, streaming rendering, and integrations with Unpoly and AdonisJS.
    async function UsersList() {
      const users = await User.all()
    
      return (
        <ul>
          {users.map((user) => (
            <li>{user.name}</li>
          ))}
        </ul>
      )
    }
    
    function App() {
      return (
        <html>
          <body>
            <UsersList />
          </body>
        </html>
      )
    }
  2. Overview of Osmosis documentation framework

    Osmosis is a framework for building documentation websites powered by AdonisJS and OsmosJS. It provides the following core features:

    • MDX Support: Ability to use JSX components within Markdown files.
    • Syntax Highlighting: Integrated code block highlighting via Shiki.
    • Flexible Content Sourcing: Documentation can be loaded from the local file system or directly from GitHub repositories.
    • Static Site Generation (SSG): Support for exporting the site to static HTML for hosting.
    • GFM Compatibility: Supports GitHub Flavored Markdown syntax.
    • Extensibility: Can be extended using remark and rehype plugins.
  3. Overview of OsmosJS for AdonisJS

    OsmosJS is a lightweight, agnostic server-side JSX runtime. The AdonisJS integration provides the necessary tools to build AdonisJS applications using JSX for server-side rendering.
  4. Use MDX and GitHub Flavored Markdown in Osmosis

    Osmosis uses MDX, which allows the integration of JSX components directly within markdown content. The system follows GitHub Flavored Markdown (GFM) standards to ensure content remains readable on GitHub.
  5. Manage global state with OsmosJS Context

    Use Context to share data (such as application themes, authenticated user info, or HTTP requests) across a component tree without passing props through every intermediate level (prop drilling). Context is implemented using NodeJS AsyncLocalStorage.
  6. Handle form submission and parsed data

    When a form is submitted, the request is sent to the same route and the component re-renders. You can check the form.isSubmitted and form.isValid properties to determine if the form was successfully processed. If valid, the parsed and validated data is available via form.parsed.
    const NewsletterForm = async () => {
      const adonis = Adonis.getOrFail()
      const form = await adonis.form(NewsletterFormSchema)
    
      if (form.isSubmitted && form.isValid) {
        await NewsletterRegistration.create({
          email: form.parsed.email,
        })
    
        return <div>You have been registered to the newsletter!</div>
      }
    
      return (
        <form method={form.method} action={form.action}>
          <input type="email" {...form.field('email')} />
          <button type="submit">Login</button>
        </form>
      )
    }
  7. Install OsmosJS in AdonisJS

    Install and configure the OsmosJS package using the AdonisJS CLI. This command automates the installation of @osmosjs/osmos, registers the necessary service providers and commands in adonisrc.ts, and generates a default configuration file at config/osmos.ts.
    node ace add @osmosjs/adonis@alpha
  8. Create and validate a form using the Adonis integration

    The Adonis integration allows you to handle form submission and validation directly within a component, eliminating the need for separate GET and POST routes. Forms are defined using a validator that supports the Standard Schema specification (such as VineJS). The adonis.form() method must be awaited because it automatically checks if the current request is submitting data and validates it against the provided schema during the component render cycle.
    import vine from '@vinejs/vine'
    import { Adonis } from '@osmosjs/adonis'
    
    const NewsletterFormSchema = vine.create({
      email: vine.string().email(),
    })
    
    const NewsletterForm = async () => {
      const adonis = Adonis.getOrFail()
      const form = await adonis.form(NewsletterFormSchema)
      // form is now available for rendering and logic
    }
  9. Create basic components in Osmos

    In Osmos, a component is a JavaScript function that returns a value capable of being rendered as HTML. This can be a literal value (like a number or string) or a JSX element. Components can be composed by nesting them within other components.
    function Header() {
      return (
        <nav>
          <a href="/">Homepage</a>
          <a href="/Blog">Blog</a>
        </nav>
      )
    }
    
    function App() {
      return (
        <html>
          <body>
            <Header />
            <main>
              <h1>Welcome!</h1>
            </main>
          </body>
        </html>
      )
    }
  10. Register a custom renderer in Osmos

    Custom renderers allow you to extend the Osmos rendering pipeline. A renderer is a function that receives an OsmosNode and returns a boolean indicating whether it handled the node. You register a custom renderer using the OsmosRenderer.register method by providing a configuration object with a unique name and a render function.
    import { OsmosRenderer } from '@osmosjs/osmos/render'
    
    OsmosRenderer.register({
      name: 'my_renderer',
      render(node, renderer) {
        // Custom rendering logic here
        // Return true if handled, false otherwise
      },
    })
  11. Forward props using ComponentProps and spread operator

    To avoid manual prop drilling, use the ComponentProps<> utility type to extract the props of an HTML tag or another component, then use the spread operator to pass them down.
    // Using HTML tag props
    function Button({ className, ...props }: ComponentProps<'button'>) {
      return <button className={['btn btn-primary', className]} {...props} />
    }
    
    // Using another component's props
    function PrimaryButton({ className, ...props }: ComponentProps<typeof Button>) {
      return <button className={['btn-primary', className]} {...props} />
    }
  12. Create and provide context values

    Create a context object using createContext. To make the context value available to a tree of components, wrap them in the Context.Provider component and pass the data via the value prop.
    import { createContext } from '@osmosjs/osmos'
    
    // Create context with an optional default value
    const AuthContext = createContext<{ user: User }>()
    
    function App({ user }: { user: User }) {
      return (
        <AuthContext.Provider value={{ user }}>
          <Toolbar />
        </AuthContext.Provider>
      )
    }