Skip to main content
Embed powerful, interactive analytics directly into your web applications using the Publisher SDK. Transform your semantic models into rich data experiences with just a few lines of code, maintaining governance and consistency across all your applications.

Overview

The Publisher SDK is a React component library that lets you embed interactive data visualizations and analytics powered by your Malloy semantic models. Build rich data applications without rebuilding your query engine.

Installation

npm install @malloy-publisher/sdk react react-dom react-router-dom @tanstack/react-query
Required Peer Dependencies:
  • react ^19.1.0
  • react-dom ^19.1.0
  • react-router-dom ^7.6.2
  • @tanstack/react-query ^5.59.16

Authentication Setup

Create a Service Account (CLI)

Coming Soon: Detailed CLI instructions for creating service accounts and issuing API keys will be added here.
To authenticate your application, you’ll need to:
  1. Create a new Group (via CLI) - e.g., embedded_apps_group
  2. Grant permissions to the Group (via CLI) - specify what data and operations the group can access
  3. Create a Service Account (CLI) with your group as the UserGroupId
  4. Issue a token - Call ServiceAccount.issueToken to generate a JWT token
  5. Store the token securely - Save the token in your application’s secure credential storage
Future API calls will act with the permissions of your assigned group. You can add or remove permissions from the group at any time, even after the token is created.

Quick Start

1. Wrap your app with ServerProvider

import { ServerProvider } from '@malloy-publisher/sdk';
import '@malloy-publisher/sdk/styles.css';

function App() {
  return (
    <ServerProvider
      baseURL="https://your-org.data.credibledata.com/api/v0"
      headers={{
        'Authorization': 'ApiKey your-api-key'
      }}
    >
      <YourComponents />
    </ServerProvider>
  );
}

2. Embed query results

The QueryResult component displays the results of a Malloy query:
import { QueryResult } from '@malloy-publisher/sdk';

export default function Dashboard() {
  return (
    <QueryResult
      resourceUri="projects/analytics/packages/sales/models/sales.malloy"
      query="run: orders -> {
        group_by: customer_segment
        aggregate: total_sales, order_count
      }"
    />
  );
}

Key Components

QueryResult

Executes and renders a Malloy query with automatic visualization.
<QueryResult
  resourceUri="projects/myproject/packages/mypackage/models/model.malloy"
  query="run: my_source -> { aggregate: count() }"
/>

// Or reference a named query
<QueryResult
  resourceUri="projects/myproject/packages/mypackage/models/model.malloy"
  sourceName="my_source"
  queryName="my_named_query"
/>
Props:
  • resourceUri (string): Path to the model (format: projects/{project}/packages/{package}/models/{path})
  • query (string, optional): Malloy query string to execute
  • sourceName (string, optional): Name of source for named query
  • queryName (string, optional): Name of query to execute

ModelExplorer

Interactive no-code query builder (Explorer) for a Malloy model:
import { ModelExplorer } from '@malloy-publisher/sdk';

export default function ExploreData() {
  return (
    <ModelExplorer
      resourceUri="projects/myproject/packages/mypackage/models/model.malloy"
      onChange={(query) => {
        console.log('User built query:', query);
        // Save or execute the query
      }}
    />
  );
}
Props:
  • resourceUri (string): Path to the model
  • onChange (function, optional): Callback when user builds a query
  • existingQuery (object, optional): Pre-populate with existing query
  • initialSelectedSourceIndex (number, optional): Which source to show initially

Notebook

Render a Malloy notebook with all its cells:
import { Notebook } from '@malloy-publisher/sdk';

export default function NotebookView() {
  return (
    <Notebook
      resourceUri="projects/myproject/packages/mypackage/models/analysis.malloynb"
    />
  );
}

Package, Project, Home

Higher-level components for building full data applications:
import { Project, Package, Home } from '@malloy-publisher/sdk';

// Browse a project's packages
<Project name="myproject" />

// Browse a package's models and notebooks
<Package name="mypackage" projectName="myproject" />

// Browse all projects
<Home />

Hooks

useRawQueryData

Execute a query and get raw JSON data (instead of rendered results):
import { useRawQueryData } from '@malloy-publisher/sdk';

function MyComponent() {
  const { data, isLoading, isError, error } = useRawQueryData({
    resourceUri: "projects/myproject/packages/mypackage/models/model.malloy",
    modelPath: "models/model.malloy",
    query: "run: my_source -> { aggregate: count() }",
    enabled: true
  });

  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error: {error.message}</div>;

  return (
    <div>
      {data.map((row, i) => (
        <div key={i}>{JSON.stringify(row)}</div>
      ))}
    </div>
  );
}

useServer

Access the server context and API clients:
import { useServer } from '@malloy-publisher/sdk';

function MyComponent() {
  const { apiClients, server, mutable } = useServer();

  // Use apiClients.projects, apiClients.packages, etc.
  // to make custom API calls
}

Advanced Configuration

Read-only Mode

Disable project/package management UI (view-only):
<ServerProvider
  baseURL="https://api.example.com/api/v0"
  mutable={false}
>

Custom Styling

The SDK includes required styles. Import them in your app:
import '@malloy-publisher/sdk/styles.css';
For additional Malloy Explorer styles:
import '@malloydata/malloy-explorer/styles.css';

Resource URI Format

Resource URIs follow this pattern:
projects/{projectName}/packages/{packageName}/models/{modelPath}
Examples:
  • projects/analytics/packages/sales/models/sales.malloy
  • projects/analytics/packages/sales/models/dashboards/revenue.malloynb
You can optionally include version:
projects/analytics/packages/sales/models/sales.malloy?versionId=abc123

Complete Example

import { ServerProvider, QueryResult, ModelExplorer } from '@malloy-publisher/sdk';
import '@malloy-publisher/sdk/styles.css';

function App() {
  return (
    <ServerProvider
      baseURL="https://your-org.data.credibledata.com/api/v0"
      headers={{
        'Authorization': 'ApiKey your-api-key'
      }}
    >
      <div>
        <h1>Sales Dashboard</h1>

        {/* Show a pre-built query */}
        <QueryResult
          resourceUri="projects/sales/packages/analytics/models/sales.malloy"
          sourceName="orders"
          queryName="monthly_revenue"
        />

        {/* Let users explore the data */}
        <h2>Explore Data</h2>
        <ModelExplorer
          resourceUri="projects/sales/packages/analytics/models/sales.malloy"
          onChange={(query) => {
            console.log('User query:', query);
          }}
        />
      </div>
    </ServerProvider>
  );
}
Need different authentication setup? We can support custom authentication flows including federated identity, SSO integration, or embedded credentials. Implementation details vary by use case—contact support@credibledata.com to discuss your requirements.

API Reference

If you prefer to build on top of the REST APIs directly without the SDK, click here for details:
I