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

@memberjunction/templates

v2.129.0

Published

MemberJunction Templating Engine and Utilities - Used for any application that requires templating utility functionality. NOTE: this package does use Angular Universal for compilation but is not marked with the usual ng prefix because it is a server-side

Readme

@memberjunction/templates

The @memberjunction/templates library provides a powerful templating engine built on Nunjucks with MemberJunction-specific extensions for dynamic content generation, AI-powered prompts, and recursive template embedding.

Overview

This package serves as the core templating engine for MemberJunction applications, offering:

  • Nunjucks-based templating with full syntax support
  • Template management with metadata integration
  • Custom extensions for AI prompts and template embedding
  • Type-safe interfaces for template rendering
  • Caching and performance optimization
  • Async rendering support

Installation

npm install @memberjunction/templates

Key Features

1. Template Engine

  • Manages template metadata and caching
  • Provides both metadata-based and simple rendering APIs
  • Integrates with MemberJunction's entity system
  • Supports template validation and parameter checking

2. AI Prompt Extension

  • Embeds AI-generated content directly in templates
  • Supports multiple AI models (OpenAI, Groq, etc.)
  • Configurable formatting options
  • Seamless integration with MemberJunction's AI Engine

3. Template Embed Extension

  • Recursive template inclusion with cycle detection
  • Content type inheritance and fallbacks
  • Data context passing and merging
  • Error handling for missing templates

Usage

Basic Template Rendering

import { TemplateEngineServer } from '@memberjunction/templates';
import { UserInfo } from '@memberjunction/core';

// Get the template engine instance
const templateEngine = TemplateEngineServer.Instance;

// Configure the engine (usually done once at startup)
await templateEngine.Config(false, contextUser);

// Simple rendering without metadata
const result = await templateEngine.RenderTemplateSimple(
    'Hello {{ name }}! Welcome to {{ company }}.',
    { name: 'John', company: 'Acme Corp' }
);

if (result.Success) {
    console.log(result.Output); // "Hello John! Welcome to Acme Corp."
}

Rendering with Template Metadata

import { TemplateEngineServer } from '@memberjunction/templates';
import { TemplateContentEntity } from '@memberjunction/core-entities';

// Assume you have loaded a template entity and its content
const templateEntity = await templateEngine.GetTemplateByName('WelcomeEmail');
const templateContent = templateEntity.GetHighestPriorityContent();

// Render with validation
const result = await templateEngine.RenderTemplate(
    templateEntity,
    templateContent,
    {
        userName: 'John Doe',
        accountType: 'Premium',
        signupDate: new Date()
    },
    false // SkipValidation = false
);

if (!result.Success) {
    console.error('Template rendering failed:', result.Message);
}

Using the AI Prompt Extension

// In your template:
const templateText = `
Dear {{ userName }},

{% AIPrompt AIModel="gpt-4", AllowFormatting=false %}
Generate a personalized welcome message for a new {{ accountType }} customer 
named {{ userName }} who just signed up for our service. Make it warm and 
professional, highlighting the benefits of their account type.
{% endAIPrompt %}

Best regards,
The Team
`;

const result = await templateEngine.RenderTemplateSimple(templateText, {
    userName: 'Sarah',
    accountType: 'Enterprise'
});

Using the Template Embed Extension

// Main template
const mainTemplate = `
{% template "Header", type="HTML" %}

<div class="content">
    <h1>Welcome {{ user.name }}</h1>
    {% template "UserProfile", data={showDetails: true} %}
</div>

{% template "Footer" %}
`;

// The embedded templates will be loaded from the template metadata
// and rendered with the appropriate content type and data context

API Reference

TemplateEngineServer

The main template engine class that handles all template operations.

Methods

Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void>

Configures the template engine and loads template metadata.

RenderTemplate(templateEntity: TemplateEntityExtended, templateContent: TemplateContentEntity, data: any, SkipValidation?: boolean): Promise<TemplateRenderResult>

Renders a template using metadata entities with optional validation.

RenderTemplateSimple(templateText: string, data: any): Promise<TemplateRenderResult>

Renders a template string without metadata integration.

GetTemplateByName(templateName: string): TemplateEntityExtended | null

Retrieves a template entity by its name.

GetTemplateByID(templateID: string): TemplateEntityExtended | null

Retrieves a template entity by its ID.

ClearTemplateCache(): void

Clears the internal template cache.

TemplateRenderResult

interface TemplateRenderResult {
    Success: boolean;     // Whether rendering succeeded
    Output: string;       // The rendered output (null if failed)
    Message?: string;     // Error message (only when Success=false)
}

Built-in Filters

The template engine provides several filters for handling complex objects and JSON data:

dump (Nunjucks built-in)

Converts any JavaScript object to a formatted JSON string.

{{ myObject | dump }}      <!-- Pretty-printed with 2 spaces -->
{{ myObject | dump(4) }}   <!-- Pretty-printed with 4 spaces -->
{{ myObject | dump(0) }}   <!-- Compact single-line format -->

json (Custom filter)

Similar to dump but with better error handling. Converts objects to JSON strings.

{{ userData | json }}      <!-- Pretty-printed with 2 spaces (default) -->
{{ userData | json(4) }}   <!-- Pretty-printed with 4 spaces -->
{{ userData | json(0) }}   <!-- Compact format -->

If serialization fails, displays: [Error serializing to JSON: <error message>]

jsoninline (Custom filter)

Converts objects to compact JSON strings (no formatting).

{{ userData | jsoninline }}  <!-- Output: {"name":"John","age":30} -->

jsonparse (Custom filter)

Parses JSON strings into JavaScript objects. Useful for processing JSON data stored as strings.

{{ '{"name":"John","age":30}' | jsonparse | json }}
<!-- First parses the string to object, then formats it -->

<!-- Access parsed object properties -->
{{ '{"name":"John","age":30}' | jsonparse | attr("name") }}
<!-- Output: John -->

Example: Handling Complex Objects

Instead of getting [object Object] in your templates:

<!-- Problem: Shows [object Object] -->
<div>User Data: {{ userData }}</div>

<!-- Solutions: Use filters to display JSON -->
<div>User Data: {{ userData | dump }}</div>
<div>User Data: {{ userData | json }}</div>
<pre>{{ userData | json(2) }}</pre>

<!-- For debugging: Compact format -->
<script>
  const data = {{ userData | jsoninline | safe }};
</script>

Combining Filters

<!-- Parse a JSON string, then format it nicely -->
{{ jsonString | jsonparse | json(4) }}

<!-- Access nested properties after parsing -->
{{ responseData | jsonparse | attr("results") | json }}

<!-- Safe output without HTML escaping -->
{{ myData | json | safe }}

Extension Configuration

AIPrompt Extension Parameters

  • AIModel (optional): Specific AI model to use (e.g., "gpt-4", "claude-3")
  • AllowFormatting (optional): Whether to allow formatted output (HTML, Markdown, etc.)

Template Embed Extension Parameters

  • First parameter: Template name (required)
  • type (optional): Specific content type to use
  • data (optional): Additional data to pass to the embedded template

Template Extension Development

To create custom template extensions:

import { TemplateExtensionBase, RegisterClass } from '@memberjunction/templates';

@RegisterClass(TemplateExtensionBase, 'MyExtension')
export class MyExtension extends TemplateExtensionBase {
    constructor(contextUser: UserInfo) {
        super(contextUser);
        this.tags = ['myTag'];
    }
    
    public parse(parser: Parser, nodes: Nodes, lexer: Lexer) {
        const tok = parser.nextToken();
        const params = parser.parseSignature(null, true);
        parser.advanceAfterBlockEnd(tok.value);
        
        const body = parser.parseUntilBlocks('endMyTag');
        parser.advanceAfterBlockEnd();
        
        return new nodes.CallExtensionAsync(this, 'run', params, [body]);
    }
    
    public run(context: Context, params: any, body: any, callBack: NunjucksCallback) {
        // Your extension logic here
        try {
            const content = body();
            // Process content...
            callBack(null, processedContent);
        } catch (error) {
            callBack(error);
        }
    }
}

Dependencies

  • @memberjunction/core: Core MemberJunction functionality
  • @memberjunction/templates-base-types: Base types and interfaces
  • @memberjunction/ai: AI integration interfaces
  • @memberjunction/aiengine: AI engine implementation
  • @memberjunction/ai-groq: Groq AI provider
  • @memberjunction/core-entities: Entity definitions
  • @memberjunction/global: Global utilities
  • nunjucks: Template engine

Integration with MemberJunction

This package integrates seamlessly with other MemberJunction packages:

  • Entity System: Templates are stored as entities with full metadata support
  • AI Engine: Direct integration for AI-powered content generation
  • User Context: Templates respect user permissions and context
  • Metadata Provider: Flexible metadata loading strategies

Configuration

The template engine uses the MemberJunction configuration system. Key configuration options:

  • Template caching strategies
  • Default AI models for prompts
  • Extension registration
  • Nunjucks environment settings

Performance Considerations

  • Templates are cached after first compilation
  • Use ClearTemplateCache() when templates are updated
  • AI prompts are processed asynchronously
  • Template embedding includes cycle detection

Error Handling

All rendering methods return a TemplateRenderResult object:

const result = await templateEngine.RenderTemplateSimple(template, data);

if (!result.Success) {
    console.error('Rendering failed:', result.Message);
    // Handle error appropriately
} else {
    // Use result.Output
}

Best Practices

  1. Always check rendering results for success before using output
  2. Configure the engine once at application startup
  3. Use template validation for user-provided data
  4. Clear cache when templates are modified
  5. Handle AI failures gracefully with fallback content
  6. Avoid deep template nesting to prevent performance issues

License

ISC - See LICENSE file for details.

Support

For issues, questions, or contributions, please visit MemberJunction.com or contact the development team.