Code Playground

Copy-paste ready code examples for common module patterns. Each example is production-ready and follows Insolitum Universe best practices.

Hello World Module

Hello World Module
'use client';

import { useShellAuth } from '@/lib/shell-auth';

export default function DashboardPage() {
  const { user, organizationId, isAuthenticated } = useShellAuth();

  if (!isAuthenticated) {
    return <p className="p-6 text-gray-400">Loading...</p>;
  }

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold text-white">
        Hello, {user?.email}!
      </h1>
      <p className="text-gray-400 mt-2">
        Organization: {organizationId}
      </p>
    </div>
  );
}

CRUD with useModuleApi

CRUD with useModuleApi
'use client';

import { useEffect, useState } from 'react';
import { useModuleApi } from '@/hooks/useModuleApi';

interface Item {
  id: string;
  name: string;
  created_at: string;
}

export default function ItemsPage() {
  const { query, insert, remove } = useModuleApi();
  const [items, setItems] = useState<Item[]>([]);
  const [name, setName] = useState('');

  useEffect(() => {
    loadItems();
  }, []);

  async function loadItems() {
    const { data } = await query('mymodule_items')
      .select('*')
      .order('created_at', { ascending: false });
    if (data) setItems(data);
  }

  async function addItem() {
    if (!name.trim()) return;
    await insert('mymodule_items', { name });
    setName('');
    loadItems();
  }

  async function deleteItem(id: string) {
    await remove('mymodule_items', { id });
    loadItems();
  }

  return (
    <div className="p-6 space-y-4">
      <h1 className="text-xl font-bold text-white">Items</h1>

      <div className="flex gap-2">
        <input
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="New item..."
          className="rounded bg-gray-800 border border-gray-700 px-3 py-2 text-white"
        />
        <button
          onClick={addItem}
          className="rounded bg-purple-600 px-4 py-2 text-white font-medium"
        >
          Add
        </button>
      </div>

      <ul className="space-y-2">
        {items.map((item) => (
          <li key={item.id} className="flex justify-between items-center bg-gray-800 rounded p-3">
            <span className="text-white">{item.name}</span>
            <button
              onClick={() => deleteItem(item.id)}
              className="text-red-400 text-sm hover:text-red-300"
            >
              Delete
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

Real-time NATS Events

Real-time NATS Events
'use client';

import { useEffect, useState } from 'react';
import { useNats } from '@/hooks/useNats';

interface TelemetryData {
  device_id: string;
  temperature: number;
  humidity: number;
  timestamp: string;
}

export default function LiveDashboard() {
  const { connected, subscribe, publish } = useNats();
  const [readings, setReadings] = useState<TelemetryData[]>([]);

  useEffect(() => {
    if (!connected) return;

    // Subscribe to telemetry events
    const unsub = subscribe('telemetry', (event) => {
      const data = event.data as TelemetryData;
      setReadings((prev) => [data, ...prev].slice(0, 50));
    });

    return unsub;
  }, [connected, subscribe]);

  // Publish a custom module event
  const sendAlert = () => {
    publish('modules.my-module.alert', {
      type: 'threshold_exceeded',
      message: 'Temperature above limit',
      timestamp: new Date().toISOString(),
    });
  };

  return (
    <div className="p-6">
      <div className="flex items-center gap-2 mb-4">
        <div className={`h-2 w-2 rounded-full ${connected ? 'bg-green-400' : 'bg-red-400'}`} />
        <span className="text-sm text-gray-400">
          {connected ? 'Connected to NATS' : 'Disconnected'}
        </span>
      </div>

      <button onClick={sendAlert} className="rounded bg-orange-600 px-4 py-2 text-white mb-4">
        Send Alert Event
      </button>

      <div className="space-y-2">
        {readings.map((r, i) => (
          <div key={i} className="bg-gray-800 rounded p-3 text-sm">
            <span className="text-blue-400">{r.device_id}</span>
            {' — '}
            <span className="text-white">{r.temperature}°C</span>
            {' / '}
            <span className="text-cyan-400">{r.humidity}%</span>
          </div>
        ))}
      </div>
    </div>
  );
}