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

academe-kit

v0.3.7

Published

Official React SDK for Academe ecosystem - Authentication, protected routes, API services, and UI components for educational management applications

Readme

Academe Kit

Official React SDK for the Academe ecosystem. Provides authentication, protected routes, API services, and UI components for building educational management applications.

npm version License: MIT

Table of Contents

Features

  • Authentication: Keycloak-based authentication with automatic token management
  • Protected Routes: Role-based access control for routes and components
  • API Client: Type-safe API client with OpenAPI-generated types
  • Services: Pre-built services for Users, Institutions, Classrooms, and more
  • UI Components: Reusable React components styled with Tailwind CSS
  • TypeScript: Full TypeScript support with comprehensive type definitions

Installation

npm install academe-kit

Peer Dependencies:

npm install react react-dom

Quick Start

import { AcademeAuthProvider, ProtectedApp, useAcademeAuth } from 'academe-kit';
import 'academe-kit/dist/index.css';

function App() {
  return (
    <AcademeAuthProvider
      realm="your-realm"
      hubUrl="https://hub.academe.com.br"
      clientId="your-client-id"
      keycloakUrl="https://auth.academe.com.br"
      apiBaseUrl="https://api.academe.com.br"
    >
      <ProtectedApp>
        <MainApp />
      </ProtectedApp>
    </AcademeAuthProvider>
  );
}

function MainApp() {
  const { user, services } = useAcademeAuth();

  return (
    <div>
      <h1>Welcome, {user?.name}</h1>
    </div>
  );
}

Authentication

AcademeAuthProvider

The main provider that wraps your application and handles authentication with Keycloak.

import { AcademeAuthProvider } from 'academe-kit';

<AcademeAuthProvider
  realm="your-realm"           // Keycloak realm name
  hubUrl="https://hub.url"     // Academe Hub URL
  clientId="your-client-id"    // Keycloak client ID
  keycloakUrl="https://kc.url" // Keycloak server URL
  apiBaseUrl="https://api.url" // Optional: API base URL (default: https://stg-api.academe.com.br)
>
  {children}
</AcademeAuthProvider>

useAcademeAuth Hook

Access authentication state and methods from any component within the provider.

import { useAcademeAuth } from 'academe-kit';

function MyComponent() {
  const {
    // State
    isInitialized,    // boolean - Provider initialization status
    user,             // AcademeUser | null - Current user data
    apiClient,        // AcademeApiClient | null - Type-safe API client
    services,         // AcademeServices | null - All available services

    // Methods
    isAuthenticated,  // () => boolean - Check authentication status
    signOut,          // () => void - Sign out and clear session
    goToLogin,        // (options?) => void - Redirect to login
    refreshUserData,  // () => Promise<void> - Refresh user data from API

    // Role checks
    hasRealmRole,     // (role: string) => boolean
    hasClientRole,    // (role: string, resource?: string) => boolean
    hasSchool,        // (schoolId: string) => boolean
  } = useAcademeAuth();

  return (
    <div>
      {isAuthenticated() ? (
        <p>Logged in as {user?.name}</p>
      ) : (
        <button onClick={() => goToLogin()}>Login</button>
      )}
    </div>
  );
}

User Object

interface AcademeUser {
  id: string;
  name: string;
  email: string;
  document?: string;
  institutionRegistrations?: InstitutionRegistration[];
  keycloakUser?: {
    name: string;
    lastName: string;
    email: string;
  };
  // ... other fields from API
}

Protected Components

ProtectedApp

Wraps your entire application to ensure authentication before rendering. Shows a loading spinner during initialization and redirects unauthenticated users to login.

import { ProtectedApp } from 'academe-kit';

<ProtectedApp
  requiredRealmRoles={['school_admin']}     // Optional: Required realm roles
  requiredClientRoles={['manage-users']}    // Optional: Required client roles
>
  <YourApp />
</ProtectedApp>

ProtectedComponent

Conditionally renders children based on user roles. Returns empty fragment if user lacks required permissions.

import { ProtectedComponent } from 'academe-kit';

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>

      {/* Only visible to admins */}
      <ProtectedComponent requiredRealmRoles={['admin_academe']}>
        <AdminPanel />
      </ProtectedComponent>

      {/* Only visible to users with specific client role */}
      <ProtectedComponent requiredClientRoles={['manage-reports']}>
        <ReportsSection />
      </ProtectedComponent>
    </div>
  );
}

ProtectedRouter

Route-level protection that shows an unauthorized message instead of hiding content.

import { ProtectedRouter } from 'academe-kit';

function AdminPage() {
  return (
    <ProtectedRouter
      requiredClientRoles={['admin-access']}
      unauthorizedMessage="You don't have permission to access this page."
    >
      <AdminDashboard />
    </ProtectedRouter>
  );
}

API Services

All services are available through the useAcademeAuth hook via services object.

const { services } = useAcademeAuth();

// Use any service
const users = await services.user.getUsers();
const institutions = await services.institution.getAll();

UserService

services.user.getMe()                          // Get current user
services.user.getUsers(params?)                // List users with filters
services.user.getUserById(id)                  // Get user by ID
services.user.createUser(body)                 // Create new user
services.user.updateUser(id, body)             // Update user
services.user.deleteUser(id)                   // Delete user
services.user.getUserGroups(id)                // Get user's groups
services.user.getUserCertificates(id)          // Get user's certificates
services.user.getUserInstitutions(id)          // Get user's institutions
services.user.syncUser(id)                     // Sync with Keycloak

InstitutionService

services.institution.getAll()                                       // List all institutions
services.institution.getById(id)                                    // Get institution by ID

// Groups
services.institution.getGroups(institutionId)
services.institution.addGroup(institutionId, data)
services.institution.updateGroup(institutionId, groupId, data)
services.institution.removeGroup(institutionId, groupId)

// Classrooms
services.institution.getClassrooms(institutionId, options?)
services.institution.getClassroomById(institutionId, classroomId)
services.institution.addClassroom(institutionId, data)
services.institution.updateClassroom(institutionId, classroomId, data)
services.institution.removeClassroom(institutionId, classroomId)

// Users & Registrations
services.institution.getUsers(institutionId, options?)
services.institution.getRegistrations(institutionId)
services.institution.getRegistrationById(institutionId, registrationId)
services.institution.getRegistrationByUserId(institutionId, userId)
services.institution.registerUser(institutionId, data)
services.institution.updateRegistration(institutionId, registrationId, data)
services.institution.assignUserToClassroom(institutionId, registrationId, data)
services.institution.removeRegistration(institutionId, registrationId)
services.institution.getGroupUsers(institutionId)

ClassroomService

services.classroom.getAll()                           // List all classrooms
services.classroom.getById(id)                        // Get classroom by ID
services.classroom.getByInstitution(institutionId, params?)
services.classroom.create(data)                       // Create classroom
services.classroom.update(id, data)                   // Update classroom
services.classroom.delete(id)                         // Delete classroom

ShiftService

services.shift.getAll()            // List all shifts
services.shift.getById(id)         // Get shift by ID
services.shift.create(data)        // Create shift
services.shift.update(id, data)    // Update shift
services.shift.delete(id)          // Delete shift

SerieService

services.serie.getAll()            // List all series
services.serie.getById(id)         // Get serie by ID
services.serie.create(data)        // Create serie
services.serie.update(id, data)    // Update serie
services.serie.delete(id)          // Delete serie

OrganizationService

services.organization.getAll(params?)     // List with filters (name, type, isActive, etc.)
services.organization.getById(id)         // Get organization by ID
services.organization.create(body)        // Create organization
services.organization.update(id, body)    // Update organization
services.organization.delete(id)          // Delete organization

ReportService

// Dashboard
services.report.getDashboard(params?)
services.report.getDashboardByInstitution(id)

// Courses by Area
services.report.getCoursesByArea()
services.report.getCoursesByAreaByInstitution(id)

// Adhesion Rate
services.report.getAdhesionRate()
services.report.getAdhesionRateByInstitution(id)

// Recent Activities
services.report.getRecentActivities(params?)              // period: '7days' | '30days' | 'all'
services.report.getRecentActivitiesByInstitution(id, params?)

// Top Students
services.report.getTopStudents(params)                    // filterType: 'nota' | 'engajamento' | 'conclusao'
services.report.getTopStudentsByInstitution(id, params)

GuardianService

services.guardian.getAll()                      // List all guardians
services.guardian.getById(id)                   // Get guardian by ID
services.guardian.create(data)                  // Create guardian
services.guardian.update(id, data)              // Update guardian
services.guardian.delete(id)                    // Delete guardian
services.guardian.getUsers(id)                  // Get guardian's students
services.guardian.assignToUser(data)            // Assign guardian to user
services.guardian.removeFromUser(guardianId, userId)

Roles

Pre-defined role constants for consistent role checking.

import { GLOBAL_ROLES, DASHBOARD_ROLES, BACKOFFICE_ROLES } from 'academe-kit';

// Available global roles
GLOBAL_ROLES.ADMIN_ACADEME  // 'admin_academe'
GLOBAL_ROLES.SCHOOL_ADMIN   // 'school_admin'
GLOBAL_ROLES.TEACHER        // 'teacher'
GLOBAL_ROLES.STUDENT        // 'student'
GLOBAL_ROLES.GUARDIAN       // 'guardian'

Usage with protected components:

import { ProtectedComponent, GLOBAL_ROLES } from 'academe-kit';

<ProtectedComponent requiredRealmRoles={[GLOBAL_ROLES.ADMIN_ACADEME]}>
  <AdminContent />
</ProtectedComponent>

UI Components

Button

import { Button } from 'academe-kit';

<Button variant="primary" size="md" onClick={handleClick}>
  Click me
</Button>

// Variants: 'primary' | 'secondary' | 'outline'
// Sizes: 'sm' | 'md' | 'lg'

Spinner

import { Spinner } from 'academe-kit';

<Spinner />

Utility: cn

Class name utility combining clsx and tailwind-merge:

import { cn } from 'academe-kit';

<div className={cn('base-class', isActive && 'active-class', className)} />

Types

All types are exported for TypeScript support:

import type {
  // Auth types
  AcademeUser,
  SecurityContextType,
  KeycloakUser,
  SecurityProviderProps,
  AcademeKeycloakContextProps,

  // Component props
  ButtonProps,

  // API types
  types,     // Entity types (User, Institution, Classroom, etc.)
  apiTypes,  // Full OpenAPI-generated types
} from 'academe-kit';

Entity Types

import { types } from 'academe-kit';

type User = types.User;
type Institution = types.Institution;
type Classroom = types.Classroom;
type Organization = types.Organization;
type Serie = types.Serie;
type Shift = types.Shift;

Development

# Install dependencies
npm install

# Run Storybook for component development
npm run dev

# Build the library
npm run build

# Build with watch mode
npm run build:watch

# Build Storybook static site
npm run build-storybook

# Generate API types from OpenAPI spec (requires API running locally)
npm run generate:api-types

Project Structure

src/
├── components/          # UI components
│   ├── Button/
│   ├── ProtectedApp/
│   ├── ProtectedComponent/
│   ├── ProtectedRouter/
│   └── ui/
├── context/             # React context providers
│   └── SecurityProvider/
├── services/            # API services
├── roles/               # Role definitions
├── types/               # TypeScript types
├── lib/                 # Utilities
└── index.ts             # Main entry point

License

MIT


Made with care by Academe