NAME

Punk::Generate - scaffold a new Punk application

SYNOPSIS

punk new MyApp
punk new MyApp --api ./openapi.json

# or from Perl
use Punk::Generate;
my @files = Punk::Generate->new(name => 'MyApp')->run;

DESCRIPTION

The generator behind punk new. It writes a complete, running application: the class with its routes, a controller, Stencil views with a wrapper, config/punk.yml, a psgi entry point and a test that starts the app and requests a page.

The skeleton ships as templates beside this module and is rendered through Template::Stencil - the same engine the generated application uses for its own views.

METHODS

new

Punk::Generate->new(
    name  => 'MyApp',          # required; a legal Perl package name
    dir   => './MyApp',        # default: the name, :: replaced by -
    api   => './openapi.json', # optional; generates the API mount
    force => 0,                # write into a non-empty directory
);

Croaks on a name that is not a legal package name.

run

Writes the tree and returns the list of paths written, relative to dir. Croaks - before writing anything - if the target directory is not empty and force was not given, or if the spec cannot be read.

name / dir / written

The application name, the target directory, and the paths written by the last run.

THE GENERATED APPLICATION

app.psgi                          chdir to the root, then MyApp->to_app
config/punk.yml                   views, static, and a commented database
lib/MyApp.pm                      routes and wiring
lib/MyApp/Controller/Web/Root.pm  the front page
root/templates/layout.tmpl        the wrapper
root/templates/welcome.tmpl       the welcome page
root/static/style.css
t/01-basic.t                      builds the app and requests /
README.md
.gitignore                        including config/punk.local.yml

app.psgi changes directory to the application root before loading the class, because punk.yml carries relative paths; that is what makes plackup app.psgi work from anywhere.

With a spec

--api adds openapi.json at the application root, mounts it under /api with the documentation UI at /docs, and generates one controller per group of operations, each with a method named for its operationId answering 501 until implemented.

Operations are grouped by their first tag when the document uses tags, and by first path segment when it does not.

Every securityScheme the document requires also gets a checker stub, in Controller::API::Auth (or the next free name, if a tag already owns that one), wired into the mount's security option - without which Punk croaks at boot naming the scheme. Those stubs refuse every request until implemented, so the operations the specification protects are not opened by a placeholder. A scheme defined in components but never required needs no checker and gets none.

SEE ALSO

Punk, Punk::Controller, Punk::Config, Punk::Mount::OpenAPI.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)