Trickster Logo

🎭 Trickster

A modern, battle-tested micro-framework for building web applications in Perl.

CPAN Version Perl Version License Coverage

Documentation • Quick Start • Examples • Contributing

Philosophy

Trickster brings contemporary web framework design to Perl while respecting CPAN traditions.

Installation

Via CPAN

cpanm Trickster

Via cpanfile

cpanm --installdeps .

Traditional CPAN

perl Makefile.PL
make
make test
make install

This will also install the trickster command-line tool.

Quick Start

Using the CLI (Recommended)

# Create a new application
trickster new myapp

# Navigate and install dependencies
cd myapp && cpanm --installdeps .

# Start the development server
trickster server

Visit http://localhost:5678

Hello World (Manual)

use Trickster;

my $app = Trickster->new;

$app->get('/', sub {
    my ($req, $res) = @_;
    return "Welcome to Trickster";
});

$app->get('/hello/:name', sub {
    my ($req, $res) = @_;
    my $name = $req->param('name');
    return "Hello, $name";
});

$app->to_app;

Run with any PSGI server:

plackup app.psgi

Features

Routing

  • Path parameters: /user/:id
  • Constraints: qr/^\d+$/
  • Named routes for URL generation
  • Multiple HTTP methods
  • Wildcard routes

Request/Response

  • JSON parsing & serialization
  • Cookie handling (secure & signed)
  • File uploads
  • Response helpers (JSON, HTML, redirects)
  • Custom headers & status codes

Templates

  • Powered by Text::Xslate
  • TTerse syntax (Template Toolkit-like)
  • Layout support
  • Template caching
  • Custom functions

Security & Validation

  • Built-in data validation
  • Exception handling (typed errors)
  • Secure cookie encryption
  • CSRF protection ready
  • XSS prevention helpers

Developer Experience

  • CLI for scaffolding & generators
  • Hot-reload development server
  • Comprehensive logging
  • PSGI/Plack middleware compatible
  • Extensive test utilities

Performance

  • Minimal overhead
  • Template caching
  • Efficient routing engine
  • Production-ready out of the box

Code Examples

REST API with JSON

use Trickster;
use Trickster::Request;
use Trickster::Response;

my $app = Trickster->new;

$app->get('/api/users/:id', sub {
    my ($req, $res) = @_;
    $req = Trickster::Request->new($req->env);
    $res = Trickster::Response->new;
    
    my $id = $req->param('id');
    my $user = get_user($id);
    
    return $res->json($user);
});

$app->post('/api/users', sub {
    my ($req, $res) = @_;
    $req = Trickster::Request->new($req->env);
    $res = Trickster::Response->new;
    
    my $data = $req->json;
    my $user = create_user($data);
    
    return $res->json($user, 201);
});

Data Validation

use Trickster::Validator;

$app->post('/register', sub {
    my ($req, $res) = @_;
    my $data = $req->json;
    
    my $validator = Trickster::Validator->new({
        name  => ['required', ['min', 3], ['max', 50]],
        email => ['required', 'email'],
        age   => ['numeric', ['min', 18]],
    });
    
    unless ($validator->validate($data)) {
        return $res->json({ errors => $validator->errors }, 400);
    }
    
    # Process valid data...
    return $res->json({ success => 1 }, 201);
});

Template Rendering

use Trickster::Template;

my $template = Trickster::Template->new(
    path => ['templates'],
    cache => 1,
    layout => 'layouts/main.tx',
);

$app->get('/profile/:username', sub {
    my ($req, $res) = @_;
    my $username = $req->param('username');
    
    my $html = $template->render('profile.tx', {
        title => 'User Profile',
        user  => get_user($username),
    });
    
    return $res->html($html);
});

Exception Handling

use Trickster::Exception;

$app->get('/user/:id', sub {
    my ($req, $res) = @_;
    my $id = $req->param('id');
    
    my $user = find_user($id);
    
    unless ($user) {
        Trickster::Exception::NotFound->throw(
            message => "User not found"
        );
    }
    
    return $res->json($user);
});

# Custom error handler
$app->error_handler(sub {
    my ($error, $req, $res) = @_;
    
    if (ref($error) && $error->isa('Trickster::Exception')) {
        return $res->json($error->as_hash, $error->status)->finalize;
    }
    
    return $res->json({ error => 'Server Error' }, 500)->finalize;
});

CLI Commands

Trickster includes a powerful command-line interface:

# Scaffold new application
trickster new myapp

# Generate components
trickster generate controller User
trickster generate model Post
trickster generate template about

# Development server with hot-reload
trickster server --reload --port 3000

# Show version
trickster version

Testing

Comprehensive test suite included:

# Run all tests
prove -l t/

# With verbose output
prove -lv t/

# Single test file
prove -lv t/01-routing.t

Test coverage: 85%+

Documentation

Examples

Check out the examples/ directory for complete working applications:

| Example | Description | Run Command | |---------|-------------|-------------| | hello.psgi | Basic routing & parameters | plackup examples/hello.psgi | | api.psgi | Full REST API with CRUD | plackup examples/api.psgi | | template.psgi | Template engine demo | plackup examples/template.psgi | | advanced.psgi | All features showcase | plackup examples/advanced.psgi | | middleware.psgi | Middleware integration | plackup examples/middleware.psgi |

Requirements

Core Dependencies

Optional

cpanm Text::Xslate
# or
cpanm --installdeps . --with-feature=templates

Contributing

Contributions are welcome. Please ensure:

See CONTRIBUTING.md for details.

License

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, under the terms of either:

See LICENSE for more details.

Author

Trickster Contributors