PHPackages                             serhiilabs/inscribe - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. serhiilabs/inscribe

ActiveLibrary[Templating &amp; Views](/categories/templating)

serhiilabs/inscribe
===================

Fluent template builder for composing text from reusable parts

1.0.1(3mo ago)01[2 PRs](https://github.com/serhiilabs/inscribe/pulls)MITPHPPHP ^8.3CI passing

Since Jan 26Pushed 1mo agoCompare

[ Source](https://github.com/serhiilabs/inscribe)[ Packagist](https://packagist.org/packages/serhiilabs/inscribe)[ Docs](https://github.com/serhiilabs/inscribe)[ RSS](/packages/serhiilabs-inscribe/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (4)Versions (5)Used By (0)

Inscribe
========

[](#inscribe)

[![Latest Version on Packagist](https://camo.githubusercontent.com/729b355cedc1e74e8844f608a01386b9f5dee23047ab5bde4713771513d55163/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7365726869696c6162732f696e7363726962652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/serhiilabs/inscribe)[![Tests](https://camo.githubusercontent.com/6cb54ad705c2f8c854e351de1997485fc837a0d66cd092ecdd9792f6b1758e56/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7365726869696c6162732f696e7363726962652f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/serhiilabs/inscribe/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/54d3ac5edb14ac6086bf70e93648be56eeb2c50b372b3f272178293ed8bdf680/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7365726869696c6162732f696e7363726962652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/serhiilabs/inscribe)[![License](https://camo.githubusercontent.com/8365034d7b0c187eab3b5f54081a1b8601c2c70a61466fb52b8a8345bafa53e4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7365726869696c6162732f696e7363726962652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/serhiilabs/inscribe)

A fluent template builder for composing text from reusable parts. Build AI prompts, email bodies, notifications, and any structured text by combining modular template files.

Why Inscribe?
-------------

[](#why-inscribe)

Building complex text output often means concatenating strings, managing conditionals, and losing track of what goes where. Inscribe solves this by letting you:

- **Compose text from reusable parts** - Write each section once, use it everywhere
- **Keep templates in separate files** - Easy to find, edit, and version control
- **Use placeholders with context** - Global defaults with local overrides
- **Build fluently** - Chain methods for readable, maintainable code

Perfect for:

- **AI Prompts** - Combine system instructions, context, and user input
- **Email Templates** - Mix headers, bodies, and signatures
- **Notifications** - Assemble messages from reusable blocks
- **Any structured text** - Documentation, reports, messages

Quick Example
-------------

[](#quick-example)

Instead of this:

```
$prompt = "You are a helpful assistant.\n\n";
$prompt .= "Context: The user is asking about {$topic}.\n\n";
$prompt .= "User question: {$question}\n\n";
$prompt .= "Please provide a detailed answer.";
```

You write templates:

```

You are a helpful assistant.
```

```

Context: The user is asking about {{topic}}.
```

```

Please provide a detailed answer.
```

And compose them:

```
use SerhiiLabs\Inscribe\Facades\Inscribe;

$prompt = Inscribe::make()
    ->context(['topic' => 'Laravel'])
    ->include('ai.system')
    ->include('ai.context')
    ->raw('User question: {{question}}', ['question' => $userInput])
    ->include('ai.instruction')
    ->build();
```

Clean, readable, and each piece is reusable.

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 12.x

Installation
------------

[](#installation)

```
composer require serhiilabs/inscribe
```

The package auto-registers with Laravel. No additional setup required.

Configuration
-------------

[](#configuration)

Publish the config file (optional):

```
php artisan vendor:publish --tag=inscribe-config
```

Usage
-----

[](#usage)

### Basic Usage

[](#basic-usage)

Create template files in your templates directory:

```

Hello, {{name}}!
```

```

Best regards,
{{sender}}
```

Build your text:

```
use SerhiiLabs\Inscribe\Contracts\TemplateBuilderInterface;

class EmailService
{
    public function __construct(
        private TemplateBuilderInterface $templates,
    ) {}

    public function buildEmail(string $name): string
    {
        return $this->templates->make()
            ->context(['sender' => 'Support Team'])
            ->include('email.header', ['name' => $name])
            ->include('email.footer')
            ->build();
    }
}
```

### Dot Notation

[](#dot-notation)

Template names map to file paths:

```
email.header              -> resources/inscribe/email/header.md
email.campaigns.welcome   -> resources/inscribe/email/campaigns/welcome.md
notifications.alert       -> resources/inscribe/notifications/alert.md

```

Template names must:

- Start with a letter or underscore
- Contain only alphanumeric characters, underscores, hyphens
- Use dots as path separators

### Context (Placeholders)

[](#context-placeholders)

Use `{{placeholder}}` syntax in templates. Provide values via context.

**Global context only** - applies to all parts:

```
$text = Inscribe::make()
    ->context(['name' => 'John', 'company' => 'Acme'])
    ->include('greeting')   // Has access to name and company
    ->include('signature')  // Has access to name and company
    ->build();
```

**Local context only** - per-part values:

```
$text = Inscribe::make()
    ->include('greeting', ['name' => 'John'])
    ->include('signature', ['name' => 'Support Team'])
    ->build();
```

**Combined** - global defaults with local overrides:

```
$text = Inscribe::make()
    ->context(['name' => 'Guest', 'date' => 'today'])
    ->include('greeting')                         // name=Guest, date=today
    ->include('greeting', ['name' => 'John'])     // name=John, date=today
    ->include('farewell', ['date' => 'tomorrow']) // name=Guest, date=tomorrow
    ->build();
```

**Priority:** Local context always wins over global for the same key.

### Raw Text

[](#raw-text)

Add text without a template file:

```
$text = Inscribe::make()
    ->include('email.header')
    ->raw('PS: {{note}}', ['note' => 'Thanks for reading!'])
    ->include('email.footer')
    ->build();
```

### Custom Separators

[](#custom-separators)

Control how parts are joined:

```
// Double newline between paragraphs
$text = Inscribe::make()
    ->separator("\n\n")
    ->include('intro')
    ->include('body')
    ->include('conclusion')
    ->build();

// No separator (direct concatenation)
$text = Inscribe::make()
    ->separator('')
    ->include('prefix')
    ->include('suffix')
    ->build();
```

### Using the Facade

[](#using-the-facade)

```
use SerhiiLabs\Inscribe\Facades\Inscribe;

$text = Inscribe::make()
    ->include('template.name')
    ->build();
```

API Reference
-------------

[](#api-reference)

MethodDescription`make()`Create a new builder instance`context(array $data)`Set global context for all parts`separator(string $sep)`Set separator between parts (default: `\n`)`include(string $name, array $context = [])`Add a template by dot-notation name`raw(string $text, array $context = [])`Add raw text with optional placeholders`build()`Compile and return the final stringExceptions
----------

[](#exceptions)

ExceptionWhen`TemplateNotFoundException`Template file not found`UnboundPlaceholderException`Placeholder in template but not in context`InvalidArgumentException`Invalid template name formatAll exceptions extend `InscribeException` for easy catching.

Artisan Commands
----------------

[](#artisan-commands)

### List Templates

[](#list-templates)

```
php artisan inscribe:list
php artisan inscribe:list --all  # Show all without limit
```

Displays available templates as a tree:

```
Available templates:

├── email/
│   ├── header
│   └── footer
└── notifications/
    └── alert

Total: 3 template(s)

```

### Validate Templates

[](#validate-templates)

```
php artisan inscribe:validate
```

Checks placeholder syntax in all templates. Detects:

- Spaces in braces: `{{ name }}` (should be `{{name}}`)
- Invalid starting characters: `{{123name}}`
- Invalid characters: `{{user.name}}`, `{{user@name}}`

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for recent changes.

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

Security
--------

[](#security)

If you discover a security vulnerability, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Serhii Bondarenko](https://github.com/serhiilabs)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance85

Actively maintained with recent releases

Popularity1

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

112d ago

PHP version history (2 changes)1.0.0PHP ^8.2

1.0.1PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/dbb284be4895c75e090dae7551a0c69d1f8148663fe12b65eccefde641c5ca64?d=identicon)[serhiilabs](/maintainers/serhiilabs)

---

Top Contributors

[![serhiilabs](https://avatars.githubusercontent.com/u/47003509?v=4)](https://github.com/serhiilabs "serhiilabs (5 commits)")

---

Tags

laravelphpprompt-engineeringtemplate-enginetext-builderlaravelaiemailnotificationsbuilderfluenttexttemplatesprompts

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/serhiilabs-inscribe/health.svg)

```
[![Health](https://phpackages.com/badges/serhiilabs-inscribe/health.svg)](https://phpackages.com/packages/serhiilabs-inscribe)
```

###  Alternatives

[chimit/prompt

Manage AI prompts in Blade style.

416.6k](/packages/chimit-prompt)[larablocks/pigeon

A more flexible email message builder for Laravel 5 including chained methods, reusable message configurations, and message layout and template view management.

143.7k](/packages/larablocks-pigeon)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
