npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@radarbase/app-kit

v0.0.2

Published

A plugin-based React Native library of widgets, components, and services for building configuration-driven health research apps

Readme

@radarbase/app-kit

A plugin-based React Native library of SDUI nodes, core services, and configuration contracts for building manifest-driven health research apps.

The repo root is the library. A runnable host template lives in starter-kit/ and consumes the library exactly the way any other study app would — clone, rename, drop in a config, ship.

radar-base-app/                 <- the library (publishable as @radarbase/app-kit)
├── src/                        <- library source (TypeScript)
│   ├── core/                   <- services: ApiService, ConfigService, AuthService, EventBus, ...
│   ├── library/
│   │   ├── sdui/               <- SDUI engine: SDUIShell, NodeRegistry, loaders, built-in nodes
│   │   └── contracts/          <- Zod schemas + type-only public contracts
│   └── index.ts                <- public API surface
├── lib/                        <- tsc build output (what consumers import)
├── starter-kit/                <- clone-and-rename host template (consumes the library)
├── docs/
├── scripts/dev.sh
├── package.json                <- main: lib/index.js, types: lib/index.d.ts
└── tsconfig.json               <- rootDir: src, outDir: lib

Features

  • SDUI engine: SDUIShell consumes a manifest + per-screen blueprint JSON files and renders the UI through a node-tree walker (NodeRenderer) with per-node error isolation.
  • Built-in nodes: layout (ViewNode, SectionNode, CardNode), content (TextNode, ActionNode), feature (SurveyTaskListNode, QuestionnaireNode, VitalsChartNode, ConnectDevicesMenuNode, CalendarNode), plus stubs for inbox / activity / alert nodes.
  • Custom nodes: register your own with NodeRegistry.getInstance().register(...); nodes receive their blueprint slice, theme, dispatch, and template variables.
  • Zod-validated configs: ManifestSchema, BlueprintSchema, and NodeSchema guard every load.
  • Pluggable loaders: ManifestLoader and BlueprintLoader accept any async source (bundled JSON, remote fetch, hybrid) with primary + fallback strategies and in-memory caching.
  • Core services: CoreServicesProvider + useCoreServices() for ApiService, ConfigService, AuthService, EventBus, DataService, etc.
  • TypeScript-first: full type definitions for the public surface.

Installation (consumer)

npm install @radarbase/app-kit

Peer dependencies (the host provides these — React Native projects already have most of them):

  • react >=16.8, react-native >=0.60
  • Optional peers used by certain services / built-in nodes:
    • @react-native-firebase/app, /analytics, /messaging, /remote-config
    • @react-native-async-storage/async-storage
    • react-native-keychain

Usage

Everything is imported from the package root. You should never reach into lib/... paths.

import {
  SDUIShell,
  NodeRegistry,
  CoreServicesProvider,
  createBundledBlueprintSource,
  useCoreServices,
  eventBus,
} from '@radarbase/app-kit';
import type { NodeProps, CoreServiceOverrides } from '@radarbase/app-kit';

Minimal host app

import React from 'react';
import {
  CoreServicesProvider,
  SDUIShell,
  createBundledBlueprintSource,
} from '@radarbase/app-kit';
import manifest from './config/app-manifest.json';
import home from './config/views/home.json';
import insights from './config/views/insights.json';

const BUNDLED_BLUEPRINTS = {
  'views/home.json': home,
  'views/insights.json': insights,
};

export default function App() {
  return (
    <CoreServicesProvider>
      <SDUIShell
        manifestSource={async () => manifest}
        blueprintSource={createBundledBlueprintSource(BUNDLED_BLUEPRINTS)}
      />
    </CoreServicesProvider>
  );
}

Consuming core services from anywhere

import { useCoreServices } from '@radarbase/app-kit';

function MyNode() {
  const { api, config, auth, eventBus } = useCoreServices();
  // call api.get(...), config.get(...), auth.signIn(...), eventBus.emit(...)
}

Registering a custom node

import { NodeRegistry } from '@radarbase/app-kit';
import type { NodeProps } from '@radarbase/app-kit';
import { Text, View } from 'react-native';

function MyCustomNode({ node, context }: NodeProps) {
  return (
    <View>
      <Text style={{ color: context.theme.textColor }}>
        {String(node.title ?? 'Hello')}
      </Text>
    </View>
  );
}

NodeRegistry.getInstance().register('MyCustomNode', MyCustomNode);

Reference it from any blueprint by "type": "MyCustomNode" — the NodeRenderer will resolve and render it. Optionally declare it in your manifest's widgetsRegistry (discovery metadata for tooling; the component must still be registered in NodeRegistry at runtime):

"widgetsRegistry": [
  { "type": "MyCustomNode", "module": "./MyCustomNode" }
]

Configuration

The library is fully configuration-driven via the SDUI multi-file format. See docs/planning/SDUI_CONFIG_DESIGN.md for the full spec.

  • app-manifest.json — lightweight entry point: app name, theme, header, tabs (each with a viewPath pointer), secondary views, custom node registry, alerts, roles, CMS endpoints.
  • views/*.json — per-screen blueprints, each a ScreenBlueprint containing a node tree under root.

Loading strategies

ManifestLoader and BlueprintLoader accept any async () => Promise<unknown> source, so hosts can plug in:

  • Bundled JSONcreateBundledBlueprintSource({ 'views/home.json': home, … }) for static imports (used by the starter kit today).
  • Remote fetchasync (path) => (await fetch(\${cdn}/${path}`)).json()` for OTA updates.
  • Hybrid — a primary source + fallback chain (e.g. remote → bundled offline copy).

Validation against the Zod schemas runs on every load; invalid blueprints throw before they reach the renderer.

Built-in nodes

| Type | Purpose | | --------------------------------- | ----------------------------------------------------------------------- | | ViewNode | Root scroll container for a screen | | SectionNode | Logical grouping with an optional header | | CardNode | Elevated surface for a child cluster | | TextNode | Static / interpolated text ({{user.firstName}} etc.) | | ActionNode | Tappable button — OpenCustomView, Navigate, OpenExternalUrl, TriggerEvent | | SurveyTaskListNode | ePRO task list (singleCard / multiCard variants) | | QuestionnaireNode | Inline or full-page questionnaire form | | VitalsChartNode | Single-metric chart (mini sparkline / detailed bar) | | ConnectDevicesMenuNode | Wearable / sensor connection status | | CalendarNode | Schedule of tasks / events (calendar / agenda variants) | | InboxItemListCoordinatorNode | Tabbed coordinator across multiple InboxItemListNodes | | InboxItemListNode | Filtered inbox list (stub until data layer lands) | | RelativeActivityTodayNode | Activity progress ring (stub demo data) | | AlertBannerNode | Inline banner (info / warning / critical) |

Development

The repo is laid out as a library + a sibling consumer app for fast feedback.

./scripts/dev.sh install     # install library + starter-kit deps
./scripts/dev.sh build       # compile src/ -> lib/
./scripts/dev.sh typecheck   # tsc --noEmit on the library
./scripts/dev.sh starter     # run the starter-kit (Expo)
./scripts/dev.sh clean       # remove lib/

Equivalent npm scripts at the repo root:

npm run build        # tsc
npm run typecheck    # tsc --noEmit
npm run clean        # rm -rf lib
npm run prepublishOnly  # clean + build (runs automatically on `npm publish`)

Editing the library

  1. Edit files under src/.
  2. Run npm run build at the repo root to refresh lib/.
  3. The starter-kit/ pins "@radarbase/app-kit": "^1.0.0". While the library is unpublished, point the starter at the workspace via either "@radarbase/app-kit": "file:../" (temporary edit, don't commit) or npm link — see starter-kit/README.md.

Editing the starter-kit

  1. cd starter-kit && npm start (or ./scripts/dev.sh starter from root).
  2. Edit starter-kit/App.tsx and starter-kit/config/**/*.json to experiment with manifests, blueprints, and custom nodes.

Publishing

prepublishOnly runs clean && build so that npm publish ships a fresh lib/ and lib/index.d.ts. Only the lib/ directory and README.md are included in the published tarball (see the files field in package.json).

License

MIT — see LICENSE.

Contributing

  1. Fork the repository.
  2. Create a feature branch.
  3. Make your changes under src/ and add a usage example in starter-kit/ if relevant.
  4. Run npm run typecheck and npm run build at the repo root before opening a PR.
  5. Submit a pull request.

Support

For questions and support, please open an issue on GitHub.