A documentation plugin that provides contextual learning journeys directly within the Grafana interface.
The Grafana Learning Journeys Plugin transforms how users interact with documentation by providing:
- π― Context-Aware Recommendations - suggestions based on current Grafana context (page, data sources, dashboard state)
- π Interactive Learning Journeys - Step-by-step guided experiences with progress tracking and milestone navigation
- ποΈ Tabbed Interface - Browser-like multi-tab experience for simultaneous documentation access
- π Extensible Architecture - Decoupled design allowing easy integration with different content sources
- π± Responsive Design - Optimized for sidebar integration with adaptive layouts
- π Auto-Launch Tutorials - Automatically open specific tutorials on Grafana startup for demo scenarios
Perfect for demo scenarios! The plugin can automatically open a specific tutorial when Grafana starts by setting an environment variable:
# Docker Compose example
GF_PLUGINS_GRAFANA_GRAFANADOCSPLUGIN_APP_TUTORIAL_URL=https://grafana.com/docs/learning-journeys/linux-server-integration/
# Docker run example
docker run -d -p 3000:3000 \
-e GF_PLUGINS_GRAFANA_GRAFANADOCSPLUGIN_APP_TUTORIAL_URL=https://grafana.com/docs/learning-journeys/linux-server-integration/ \
grafana/grafana:latest
π Complete Auto-Launch Documentation - Detailed setup guide with examples for Docker, Kubernetes, and more.
Clone the repository:
git clone https://github.com/grafana/docs-plugin.git
Then build the plugin:
cd docs-plugin
npm install
npm run build
Spin up the development server:
Note we are currently using main until the next release of Grafana.
GRAFANA_IMAGE=grafana GRAFANA_VERSION=main npm run server
Access the plugin in Grafana at http://localhost:3000
This plugin follows a modular, well-documented architecture. Each major component has detailed documentation:
- Source Overview - Complete source code organization and patterns
- Component Architecture - UI component organization and relationships
- App Component - Root application setup and scene integration
- App Configuration - Admin settings and plugin configuration
- Documentation Panel - Main docs functionality and tabbed interface
- Pages & Routing - Scene-based routing and navigation
- Utilities & Hooks - Business logic, data fetching, and React hooks
- Styling System - CSS-in-JS organization and theming
- Constants & Configuration - Centralized configuration and selectors
- Image Assets - Plugin logos and visual assets
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Grafana Core Application β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Plugin Extension Points β
β βββββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β Sidebar Componentβ β Navigation Links β β
β βββββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Learning Journeys Plugin β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββ β
β β Context Panel β β Journey Panel β β App Core β β
β β β β β β β β
β β β’ Recommendationsβ β β’ Tab Managementβ β β’ Routing β β
β β β’ Context Detectionβ β β’ Content Displayβ β β’ State β β
β β β’ User Interaction β β β’ Navigation β β β’ Config β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββ β
β β β β β
β βββββββββββββββββββββββββΌββββββββββββββββββββββ β
β β β
ββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Data Layer (Decoupled) β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββ β
β β Docs Fetcher β β Recommender API β β Cache β β
β β β β β β β β
β β β’ Content Fetch β β β’ Context Analysisβ β β’ In-Memory β β
β β β’ HTML Parsing β β β’ ML Recommendationsβ β β’ Persistentβ β
β β β’ URL Resolutionβ β β’ Journey Mapping β β β’ Invalidationβ β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββ β
β β β β β
β βββββββββββββββββββββββββΌββββββββββββββββββββββ β
β β β
ββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β External Data Sources β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββ β
β β Grafana.com Docsβ β Custom CMS β β Local Docs β β
β β Learning Journeysβ β Documentation β β Files β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The plugin follows a modular, scene-based architecture using Grafana Scenes. See the Documentation Panel README for detailed component relationships and the Utilities README for the refactored business logic organization.
This codebase underwent major refactoring to improve maintainability:
- Before: Single component with ~3,500 lines mixing UI, business logic, and styling
- After: Organized into focused, reusable modules with clear separation of concerns
Key Improvements:
- Extracted React Hooks - Business logic separated into reusable hooks
- Organized Styling - Theme-aware CSS-in-JS with logical grouping
- Centralized Constants - Type-safe configuration and selectors
- Clean Components - Focused UI components with single responsibilities
User Opens Grafana
β
βΌ
Plugin Loads via Extension Points
β
βΌ
Context Panel Analyzes Current State
β’ Current URL/Path
β’ Active Data Sources
β’ Dashboard Information
β’ User Session Data
β
βΌ
Recommendation Service Called
β’ Sends context payload
β’ Receives relevant journeys
β’ Pre-fetches milestone information
β
βΌ
UI Renders with Recommendations
User Clicks "Start Journey"
β
βΌ
New Tab Created
β’ Generates unique tab ID
β’ Sets initial loading state
β’ Adds to tab collection
β
βΌ
Content Fetching Initiated
β’ docs-fetcher.fetchLearningJourneyContent()
β’ Multiple strategy fallback system
β’ HTML parsing and transformation
β
βΌ
Content Rendered
β’ Milestone progress indicator
β’ Interactive content with fixed assets
β’ Navigation controls
β’ Video integration
β
βΌ
User Navigates Through Milestones
β’ Previous/Next milestone buttons
β’ Direct milestone jumping
β’ Progress tracking
β’ Cache optimization
βββββββββββββββββββ Context Analysis βββββββββββββββββββ
β Context Panel β βββββββββββββββββββββββ β Recommender API β
β β β β
β β’ Page Detectionβ βββββββββββββββββββββββ β β’ ML Processing β
β β’ Data Sources β Journey Suggestions β β’ Journey Map β
β β’ Dashboard Infoβ β β’ Relevance β
βββββββββββββββββββ βββββββββββββββββββ
β β
β User Selects Journey β
βΌ β
βββββββββββββββββββ Content Request βββββββββββββββββββ
β Journey Panel β βββββββββββββββββββββββ β Docs Fetcher β
β β β β
β β’ Tab Manager β βββββββββββββββββββββββ β β’ Multi-Strategyβ
β β’ UI Renderer β Processed Content β β’ HTML Parser β
β β’ Navigation β β β’ Asset Fixer β
βββββββββββββββββββ βββββββββββββββββββ
β
β Raw Content
βΌ
βββββββββββββββββββ
β Content Sources β
β β
β β’ Grafana Docs β
β β’ Custom CMS β
β β’ Local Files β
βββββββββββββββββββ
The docs fetcher is intentionally designed as a decoupled, pluggable system that can be easily replaced or extended without affecting the rest of the plugin. This enables teams to:
- Replace content sources (switch from Grafana.com to internal docs)
- Customize content processing (add custom parsing logic)
- Implement different fetching strategies (GraphQL, REST APIs, file systems)
- Maintain UI functionality (all existing features continue to work)
For detailed information on the docs fetcher architecture and how to customize it, see the Utilities Documentation.
The decoupling is achieved through well-defined TypeScript interfaces that act as contracts:
// Core data structures that UI components depend on
export interface LearningJourneyContent {
title: string; // Display title
content: string; // Processed HTML content
url: string; // Source URL
currentMilestone: number; // Progress indicator
totalMilestones: number; // Total steps
milestones: Milestone[]; // Navigation structure
lastFetched: string; // Cache metadata
videoUrl?: string; // Optional video content
}
export interface Milestone {
number: number; // Step sequence
title: string; // Step name
duration: string; // Estimated time
url: string; // Step URL
isActive: boolean; // Current step indicator
}
The current fetcher implements a resilient approach with multiple fallback strategies for content retrieval. See the Utilities README for comprehensive details on the data fetching architecture and customization options.
- Node.js 18+ and npm
- Grafana 11.0.0 or later
- Git
- Docker (for development environment)
# Clone the repository
git clone https://github.com/grafana/grafana-docs-plugin.git
cd grafana-docs-plugin
# Install dependencies
npm install
# Build the plugin
npm run build
# Start development environment with Grafana
GRAFANA_IMAGE=jayclifford349/grafana-oss GRAFANA_VERSION=docs npm run server
The plugin includes a complete development setup:
# Development build with watch mode
npm run dev
# Run tests
npm run test
# Lint code
npm run lint
# Type checking
npm run typecheck
# Build for production
npm run build
For a comprehensive understanding of the project structure, see:
- Source Organization - Complete overview of the
/src
directory - Component Structure - UI components and their relationships
- Business Logic - Hooks, utilities, and data fetching
- Styling System - CSS-in-JS organization and theming
- βοΈ React - UI framework with hooks and context
- π Grafana Scenes - Scene-based architecture for complex UIs
- π TypeScript - Full type safety and IntelliSense
- π Emotion - CSS-in-JS with theme integration
- π¨ Grafana UI - Consistent component library
- π Extension Points - Grafana plugin integration system
// Configure external recommendation service
export const RECOMMENDER_SERVICE_URL = 'http://localhost:8080';
// Custom documentation endpoints
const customEndpoints = {
apiUrl: 'https://docs.company.com/api',
apiKey: 'your-secret-key'
};
For detailed configuration options, see the App Configuration README.
For detailed API documentation, see:
- Documentation Panel API - Main panel functionality
- Utilities API - Business logic and data fetching hooks
- Configuration API - Plugin configuration
// Debug content fetching
console.log('Fetching strategies attempted:', strategies);
console.log('Final content result:', content);
// Check network connectivity
fetch(url).then(response => console.log('Direct access:', response.status));
// Verify service connectivity
const healthCheck = await fetch(`${RECOMMENDER_SERVICE_URL}/health`);
console.log('Recommender service status:', healthCheck.status);
// Debug context payload
console.log('Context sent to recommender:', payload);
// Clear all caches manually
clearLearningJourneyCache();
localStorage.clear();
window.location.reload();
# Analyze bundle composition
npm run build:analyze
# Check for duplicate dependencies
npm run dedupe
// Implement progressive loading
const preloadNextMilestone = async (content: LearningJourneyContent) => {
const nextUrl = getNextMilestoneUrl(content);
if (nextUrl) {
// Pre-fetch in background
fetchLearningJourneyContent(nextUrl);
}
};
For more troubleshooting information, see the component-specific documentation linked above.
// Add to console for detailed logging
localStorage.setItem('docs-plugin-debug', 'true');
// Monitor scene state changes
console.log('Scene state:', sceneObject.state);
// Monitor all fetch requests
const originalFetch = window.fetch;
window.fetch = (...args) => {
console.log('Fetch request:', args);
return originalFetch(...args);
};
- TypeScript: Strict mode enabled
- React: Functional components with hooks
- Styling: Emotion CSS-in-JS with Grafana theme
- Testing: Jest + React Testing Library
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Test your changes thoroughly
- Commit with conventional commit messages
- Push to your branch (
git push origin feature/amazing-feature
) - Open a Pull Request
# 1. Set up development environment
npm install
npm run dev
# 2. Make changes and test
npm run test
npm run typecheck
npm run lint
# 3. Build and verify
npm run build
npm run server # Test in Grafana
# 4. Submit changes
git add .
git commit -m "feat: add custom content source support"
git push origin feature/custom-content
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- π Grafana Plugin Development
- π Grafana Scenes Documentation
- βοΈ React Best Practices
- π TypeScript Handbook