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

@seliseblocks/app-kit

v0.1.2

Published

Shared React components, layouts, providers, authentication and utilities for SELISE Blocks applications.

Readme

@seliseblocks/app-kit

React app-shell composition package for SELISE Blocks applications: guards, layouts, providers, pages, stores, hooks, an HTTP client, and a shadcn/Radix based component library. It is the shared frontend foundation consumed by the Blocks service applications (IAM, OS, Data, Logic, Monitor, Release, Studio, Utilities, Localization).

Ships as ESM and CJS with bundled TypeScript declarations. Every module carries a "use client" banner, and runtime initialization is preserved across entry points.

Installation

npm install @seliseblocks/app-kit
# or
yarn add @seliseblocks/app-kit
# or
pnpm add @seliseblocks/app-kit

Peer Dependencies

Your application must provide these packages (@types/react is optional, for TypeScript users):

{
  "@tanstack/react-query": "^5.0.0",
  "nuqs": "^2.9.0",
  "react": "^19.2.0",
  "react-dom": "^19.2.0",
  "react-router": "^8.0.0",
  "zustand": "^5.0.0"
}

Styling Contract

This package intentionally ships no CSS files. Host applications are responsible for:

  • Tailwind CSS setup, including scanning this package's dist output so its utility classes are generated:

    // tailwind.config.ts
    export default {
      content: ["./app/**/*.{ts,tsx}", "./node_modules/@seliseblocks/app-kit/dist/**/*.{js,jsx,ts,tsx}"],
    };
  • Tailwind CSS setup

  • shared design tokens (CSS variables) for theming

  • Any global CSS imports required by their design system

Runtime Configuration

Service base URLs and keys are read at runtime, not baked in at build time. Provide them on window.__BLOCKS_ENV__ before the app boots (typically an inline script in index.html), or through import.meta.env in ESM/Vite builds. CommonJS builds use the runtime window configuration:

<script>
  window.__BLOCKS_ENV__ = {
    BLOCKS_IAM_BASE_URL: "https://iam.example.com",
    BLOCKS_LOGIC_BASE_URL: "https://logic.example.com",
    BLOCKS_X_BLOCKS_KEY: "your-blocks-key",
  };
</script>

Read values with getRuntimeEnv from @seliseblocks/app-kit/lib. The full key list is the RuntimeKey union exported from @seliseblocks/app-kit/types (per-service *_BASE_URL, *_CLIENT_ID, and *_CALLBACK_URL keys plus BLOCKS_X_BLOCKS_KEY and others).

Quick Start

Wrap your app in the providers, then compose routes from the guards, layouts, and pages:

import { NuqsAdapter } from "nuqs/adapters/react-router/v8";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { createBrowserRouter, Navigate, Outlet, RouterProvider } from "react-router";

import { AuthResolver, ProtectedGuard, PublicGuard } from "@seliseblocks/app-kit/guards";
import { ConsoleLayout } from "@seliseblocks/app-kit/layouts";
import { CallbackPage, ConsolePage, LoginPage, ProfilePage } from "@seliseblocks/app-kit/pages";
import { BlocksAppLayout, QueryProvider, ThemeProvider } from "@seliseblocks/app-kit/providers";

const router = createBrowserRouter([
  {
    path: "/login/callback",
    element: <CallbackPage defaultRedirectUrl="/app/console" />,
  },
  {
    element: (
      <AuthResolver>
        <Outlet />
      </AuthResolver>
    ),
    children: [
      {
        element: (
          <PublicGuard>
            <Outlet />
          </PublicGuard>
        ),
        children: [{ path: "/login", element: <LoginPage /> }],
      },
      {
        path: "/app",
        element: (
          <ProtectedGuard>
            <ConsoleLayout>
              <Outlet />
            </ConsoleLayout>
          </ProtectedGuard>
        ),
        children: [
          { index: true, element: <Navigate to="console" replace /> },
          { path: "console", element: <ConsolePage /> },
          { path: "profile", element: <ProfilePage /> },
        ],
      },
    ],
  },
]);

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <QueryProvider>
      <ThemeProvider>
        <NuqsAdapter>
          <BlocksAppLayout
            config={{
              name: "blocks-monitor",
              appLogoUrl: { dark: "/logo-dark.svg", light: "/logo-light.svg" },
            }}
          >
            <RouterProvider router={router} />
          </BlocksAppLayout>
        </NuqsAdapter>
      </ThemeProvider>
    </QueryProvider>
  </StrictMode>,
);

BlocksAppLayout takes a config with the service name (one of the ServiceName union values, for example "blocks-os" or "blocks-monitor") and an appLogoUrl (a string, or { dark, light } variants).

Package Exports

The main entry (@seliseblocks/app-kit) re-exports everything below. Subpath imports keep intent clearer and are what the Blocks applications use.

| Subpath | Contents | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ./guards | AuthResolver, ProtectedGuard, PublicGuard, ImpersonationChecker, ImpersonationSynchronizer, ImpersonationTerminator | | ./layouts | AuthLayout, ConsoleLayout, DashboardLayout, DashboardRoute, OidcLayout, PublicLayout, useOidcContext | | ./providers | BlocksAppLayout, QueryProvider, ThemeProvider, DashboardLayoutProvider, getQueryClient | | ./pages | CallbackPage, ConsolePage, DashboardOverview, LoginPage, ProfilePage | | ./store | useAuthStore, useAppSettingsStore, useImpersonateStore, useLanguageViewStore, useProjectStore, useUserStore, CreateAppConfigStore | | ./hooks | See Hooks below | | ./components | See Components below | | ./lib | See HTTP Client and Lib below | | ./utils | General-purpose helpers, see Utils below | | ./models | Domain models: AuthStateShape, AuthTokenPair, BaseUser, UserDetails, IProject, IProjectGroup, IDomain, IEnvRepository, INotification, IMyOrganization, ImpersonationState, RegisteredService, and related payload/response types | | ./types | Shared types: ApiResponse, ApiError, ApiErrorResponse, ApiPaginatedResponse, BaseRequestParams, Menu, NavigationMenuItem, NavigationNode, RuntimeKey, ProjectKey, Id |

Components

@seliseblocks/app-kit/components bundles two groups:

  • Core components (Radix UI + shadcn based): Accordion, Alert, AlertDialog, AspectRatio, Avatar, Badge, Breadcrumb, Button, Calendar, Card, Carousel, ChartContainer, Checkbox, Collapsible, Command, ContextMenu, CopyToClipboardButton, DateRangePicker, Dialog, Drawer, DropdownMenu, FileUploader, Form, HoverCard, InfiniteScroller, Input, InputOTP, KanbanBoard, Label, MaskedText, Menubar, MultiSelect, NavigationMenu, Pagination, PasswordInput, Popover, Progress, RadioGroup, RenderConditionally, RenderAlternatively, ResizablePanel, ScrollArea, Select, Separator, Sheet, Sidebar, Skeleton, Slider, Spinner, Stepper, Switch, Table, TablePagination, Tabs, Textarea, Timeline, Toast, Toaster, Toggle, ToggleGroup, Tooltip, and the WizardStepper family, along with their subcomponents (CardContent, DialogTrigger, SelectItem, and so on).

  • Common composites: AppSwitcher, ArchiveProject, BackToConsoleNavigator, ConfirmationModal, ConsoleHeader, CopyableSnippet, DashboardHeader, DashboardSectionCard, DataTable, EnvironmentCard, EnvironmentList, EnvironmentSelected, ErrorBoundary, ErrorDisplay, FilterToolbar, ImportFileModal, LanguageSelector, LoaderSpinner, LoadingButton, LoginHeader, Logo, LogoutButton, ModeToggle, Notification, NotificationBell, NotificationHeader, NotificationItem, NotificationList, ProjectList, ProjectDetail, ProjectEdit, ProjectActions, SidebarMenu, ThemeSwitcher, UserDropdownMenu, and more.

import { Button, Card, CardContent } from "@seliseblocks/app-kit/components";

function MyComponent() {
  return (
    <Card>
      <CardContent>
        <Button variant="default">Click Me</Button>
      </CardContent>
    </Card>
  );
}

Hooks

State and UI helpers: useBoolean, useCopyToClipboard, useCountDown, useDebounce, useMediaQuery, useIsMobile, usePathSegments, usePopoverWidth, useTheme, useToast, useIcon, useLogo, useScopedPath, useBlocksAppConfigStore.

Search: useFuseIndex, useFuseSearch, useDebouncedFuseFilter.

Query helpers: useQueryClientKit, useQueryStatesKit, createQueryKeyFactory.

Domain data (TanStack Query backed): useGetProject, useGetProjects, useUpdateProject, useDisableProject, useGetEnvRepositories, useGetAllServices, useGetMyOrganizations, useGetNotifications, useMarkAsRead, useMarkAllAsRead, useStartImpersonation, useStopImpersonation, useImpersonationStatusChecker, useInitiateRedirect, usePrefetchRedirect, useLanguage, useLanguageSwitcher, useLogout, useFilteredMenus, useIsActiveMenu.

import { useBoolean, useToast } from "@seliseblocks/app-kit/hooks";

function MyComponent() {
  const { toast } = useToast();
  const { value: isOpen, toggle } = useBoolean(false);

  return (
    <button
      onClick={() => {
        toggle();
        toast({ title: isOpen ? "Closed" : "Opened" });
      }}
    >
      Toggle
    </button>
  );
}

HTTP Client and Lib

@seliseblocks/app-kit/lib exports:

  • HttpClient and HttpError: a fetch-based client with Blocks key headers, token refresh queueing, and auth-failure redirects
  • Preconfigured instances wired to the runtime env: iamClient, logicClient, notificationClient
  • getRuntimeEnv, createRuntimeEnvGetter, resolveBaseUrl, resolveEnv
  • CookieStorage, cn, theme helpers (applyTheme, getSystemTheme), and motion presets (fadeInUp, fadeInScale, fadeTransition, motionEase, staggerContainer, staggerItem)
import { getRuntimeEnv, HttpClient, logicClient } from "@seliseblocks/app-kit/lib";

// Use a preconfigured instance:
async function fetchProjects() {
  return logicClient.get("/api/Project/Gets?page=0&pageSize=100");
}

// Or configure your own:
const client = new HttpClient({
  baseURL: () => getRuntimeEnv("BLOCKS_LOGIC_BASE_URL"),
  blocksKey: () => getRuntimeEnv("BLOCKS_X_BLOCKS_KEY"),
});

Utils

@seliseblocks/app-kit/utils covers formatting (formatDate, formatFullDate, formatNumber, formatCurrency, formatBytes, formatFileSize, formatDuration), objects and arrays (pick, omit, deepClone, deepEqual, deepMerge, groupBy, uniqueBy), functions (debounce, throttle, memoize, sleep), validation (isEmail, isUrl, isUuid, isPhone, isValidDomain, isValidSubdomain), query strings (parseQueryString, stringifyQueryString), ids (generateId, getUniqueID), storage (createStorage, createCookieStore), error handling (getErrorMessage, handleErrorMessages, hasErrorCode), and toast helpers (showSuccessToast, showErrorToast, showInfoToast).

Versioning and compatibility

The new package starts at 0.1.0. Existing public exports and subpaths are preserved; future changes to those APIs should be coordinated across Blocks applications.

License

MIT (c) SELISE Blocks

Local development and publishing

The console resolves this package to its local entries/ source through Vite and TypeScript aliases. Other applications install the published package. Internal @app-kit/ paths are bundled and do not need aliases in consuming applications.

From client/, run:

npm run build:app-kit
npm run pack:app-kit

The first release uses version 0.1.0. Inspect the tarball before publishing. From this package directory, an npm account with publishing access to the @seliseblocks scope can run:

npm publish --access public

Publishing runs the type check and builds the package. Only compiled output, this README, the license and package metadata are included; tests and local source instructions stay out of the tarball. No publication is performed by the console build.

Migration

Replace imports from @seliseblocks/genesis-os with @seliseblocks/app-kit, keeping the existing subpaths and exported symbols. The existing published genesis-os package is unaffected.

Shared application shell

AppShell from @seliseblocks/app-kit/layouts owns the top bar, desktop/mobile sidebar, workspace switcher, theme controls and account menu. AppSidebar, AppTopbar and WorkspaceSwitcher are also exported from ./components.

import { AppShell } from "@seliseblocks/app-kit/layouts";

<AppShell sidebar sections={scopedNavigationSections} onOpenCommand={openCommandMenu}>
  <Outlet />
</AppShell>

Use it inside the app-kit auth/impersonation guards and the existing BlocksAppLayout, query and theme providers. The host supplies its filtered, URL-scoped navigation and command-menu opener; no sidebar markup or tenant switching code is required in the host. Omit sidebar for console/profile pages.

The workspace picker loads projects only when opened, groups environments under projects, disables unavailable environments, and establishes impersonation before updating selection and navigating to /app/:itemId/dashboard. Standalone WorkspaceSwitcher consumers can override environmentPath and receive onNavigate to close their own mobile drawer. Errors preserve the selection and route and show feedback; a failed list query offers retry.

Tailwind 4 hosts should expose the usual semantic sidebar colours, for example:

@theme {
  --color-sidebar: hsl(var(--background));
  --color-sidebar-foreground: hsl(var(--foreground));
  --color-sidebar-border: hsl(var(--border));
  --color-sidebar-accent: hsl(var(--accent));
  --color-sidebar-accent-foreground: hsl(var(--accent-foreground));
  --color-sidebar-ring: hsl(var(--ring));
}

Continue scanning the package's dist directory for Tailwind utilities.