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)