Granite Documentation

repository·main·Indexed 19 days ago

https://github.com/toss/granite

A Gradle plugin that enables React Native features, including TurboModules, Fabric, and JS bundling, within Android Library modules (AAR). The ecosystem includes @granite-js/forge for application management and @granite-js/pulumi-aws for automating React Native CDN infrastructure on AWS using the ReactNativeBundleCDN component.

Tokens
110.6K
Snippets
417
Records
568
Agent score
66%

What's inside Granite

  1. Use @granite-js/forge to manage Granite applications

    main
    @granite-js/forge is a command-line interface (CLI) tool designed for managing Granite applications. It provides the necessary tooling to handle application lifecycles and management tasks within the Granite ecosystem.
  2. How layout application scope and nesting works

    main

    The scope of a _layout.tsx file is determined by its location in the file system:

    • pages/_layout.tsx: Applies to all pages in the application (Global Layout).
    • pages/about/_layout.tsx: Applies to all pages within the about directory (e.g., <scheme>://{serviceName}/about/index and <scheme>://{serviceName}/about/team).

    Nesting: Layouts are applied sequentially from the top-level directory down to the specific page. For a file at pages/about/team.tsx, the application order is:

    1. pages/_layout.tsx (Top-level)
    2. pages/about/_layout.tsx (Section-level)
    3. pages/about/team.tsx (The page itself)
  3. Understand the Pulumi Project Layout

    main

    The template follows a standard Pulumi TypeScript structure:

    • Pulumi.yaml: Contains Pulumi project and template metadata.
    • index.ts: The main Pulumi program where resources (like the S3 bucket) are defined.
    • package.json: Manages Node.js dependencies.
    • tsconfig.json: Defines TypeScript compiler options.
  4. Use automatically generated type definitions for safe routing

    main

    The router plugin automatically generates type definitions in a file (typically src/router.gen.ts) that augments the @granite-js/react-native module. It populates the RegisterScreenInput and RegisterScreen interfaces with your specific paths and their corresponding input/output types. This ensures that if you attempt to navigate to a non-existent path or provide incorrect parameters, TypeScript will throw an error during development.

    // src/router.gen.ts
    
    /* eslint-disable */
    // This file is auto-generated by @granite-js/react-native. DO NOT EDIT.
    import { Route as _PageARoute } from '../pages/page-a';
    import { Route as _PageBRoute } from '../pages/page-b';
    import { Route as _PageCRoute } from '../pages/page-c';
    
    declare module '@granite-js/react-native' {
      interface RegisterScreenInput {
        '/page-a': (typeof _PageARoute)['_inputType'];
        '/page-b': (typeof _PageBRoute)['_inputType'];
        '/page-c': (typeof _PageCRoute)['_inputType'];
      }
    
      interface RegisterScreen {
        '/page-a': (typeof _PageARoute)['_outputType'];
        '/page-b': (typeof _PageBRoute)['_outputType'];
        '/page-c': (typeof _PageCRoute)['_outputType'];
      }
    }
  5. Understand the Granite project structure

    main

    A standard Granite project follows this structure:

    • pages/: Contains screen files. Each file in this directory becomes a route/screen in your app (e.g., index.tsx is the home screen).
    • src/: Core source code.
      • _app.tsx: The main microservice entry point for shared logic across all screens.
      • router.gen.ts: Auto-generated file providing type-safe routing.
    • granite.config.ts: The main configuration file for your Granite app.
    • react-native.config.js: React Native specific settings.
    • require.context.ts: Auto-generated routing context.
  6. Use ImpressionArea to detect component visibility

    main

    The ImpressionArea component detects when its child component becomes visible on the screen and triggers callbacks. This is useful for logging impressions, triggering animations, or managing resource usage when a component enters or leaves the viewport.

    Important Requirements:

    • By default, ImpressionArea must be used inside an IOScrollView to function correctly.
    • If you use it outside of IOScrollView, you must set the UNSAFE__impressFallbackOnMount prop to true to detect visibility based on the component's mount time. Failing to do this while outside an IOScrollView will result in an IOProviderMissingError.
    import { ImpressionArea, IOScrollView } from '@granite-js/react-native';
    
    <IOScrollView>
      <ImpressionArea
        onImpressionStart={() => console.log('Visible!')}
        onImpressionEnd={() => console.log('Hidden!')}
      >
        <MyComponent />
      </ImpressionArea>
    </IOScrollView>