Documentation

Web Template

New
Browse documentation

Published 2026-08-13. V2 is a prerelease; the web core is release-gated and other previews are named separately. What beta means.

Read this page as HTML, Markdown, or structured JSON—or open the published Markdown with an AI assistant. Gemini receives the prompt through your clipboard because its signed-out page does not reliably prefill URL text; paste when the new tab opens. External assistants need the public site URL.

1.4.1
Unavailable in this version
1.5
Unavailable in this version

Amber V2 Web Template

Amber CLI 2.0.6 generates a complete server-rendered web application with ECR, Grant ORM, Micrate migrations, and SQLite. The first database-backed feature needs no database server, Node.js process, or front-end package manager. The same template includes the released build-time asset manifest, so its homepage exercises the frontend contract documented for production apps.

Run from: the parent directory where my_app/ should be created.

Terminal
amber new my_app --type web
cd my_app

Web, ECR, and SQLite are the defaults, so amber new my_app is equivalent. Use -d pg or -d mysql when the application should start with a server database.

Where the examples go

Commands on this page run from the generated application root unless a closer label says otherwise. Every code or tree example names its source file, generated output, or reference role. Replace my_app with the actual generated target name when a command includes it.

Generated project

Generated output: the top-level structure under my_app/.

File tree
my_app/
├── .amber.yml
├── .gitignore
├── README.md
├── shard.yml
├── config/
│   ├── application.cr
│   ├── assets.cr
│   ├── database.cr
│   ├── routes.cr
│   └── environments/
│       ├── development.yml
│       ├── production.yml
│       └── test.yml
├── db/
│   ├── migrations/
│   └── seeds.cr
├── app/assets/                                  # authored; source control
│   ├── stylesheets/app.css
│   ├── javascript/app.js
│   ├── images/amber-crystal.svg
│   ├── images/favicon.svg
│   ├── fonts/.gitkeep
│   └── files/.gitkeep
├── public/
│   ├── assets/                                  # generated; gitignored
│   │   ├── manifest.json
│   │   └── ...fingerprinted files...
│   └── robots.txt
├── spec/
│   ├── spec_helper.cr
│   ├── controllers/home_controller_spec.cr
│   └── channels, jobs, mailers, models, requests, schemas/
└── src/
    ├── my_app.cr
    ├── controllers/
    │   ├── application_controller.cr
    │   └── home_controller.cr
    ├── views/
    │   ├── home/index.ecr
    │   └── layouts/application.ecr
    └── channels, jobs, mailers, models, schemas, sockets/

The empty extension directories give generators stable destinations. The generated README.md names those destinations again while a developer is working inside the project.

Exact dependency contract

File: shard.yml — generated dependency manifest.

YAML
crystal: ">= 1.20.0, < 2.0"

dependencies:
  amber:
    github: amberframework/amber
    version: 2.0.0-beta.5
  grant:
    github: crimson-knight/grant
    commit: 2665a978b43ac608c68cde9243821f8f8f053372
  asset_pipeline:
    github: amberframework/asset_pipeline
    version: 0.37.0
  sqlite3:
    github: crystal-lang/crystal-sqlite3
    version: ~> 0.23.0

The exact Grant commit is intentional while its V2 release is finalized. Amber and Grant changes are not pulled from moving branches during application generation.

The CLI embeds its web scaffold in the executable. amber new does not fetch a template manifest, so updating the CLI changes future projects but never silently rewrites an existing application.

Database connection

File: config/database.cr — generated SQLite registration.

Crystal
require "amber"
require "grant"
require "grant/adapter/sqlite"

Grant::Connections << Grant::Adapter::Sqlite.new(
  name: "primary",
  url: ENV["DATABASE_URL"]? || Amber.settings.database_url
)

Every generated Grant model declares connection primary. DATABASE_URL overrides the environment YAML, which makes production configuration explicit without putting credentials in source control.

File: config/environments/development.yml — generated development values.

YAML
name: my_app

server:
  host: 127.0.0.1
  port: 3000
  secret_key_base: "generated-development-secret"

database:
  url: "sqlite3:./db/my_app_development.db"

session:
  key: "my_app.session"
  store: "signed_cookie"
  adapter: "memory"
  expires: 0

logging:
  severity: "debug"
  colorize: true

config/environments/test.yml uses db/my_app_test.db. Production leaves the URL empty so deployment must provide DATABASE_URL.

Generate the first persisted resource

Run from: the application root beside shard.yml.

Terminal
amber generate scaffold Pet name:string:required species:string:required adopted:bool
amber database migrate
AMBER_ENV=test amber database migrate
crystal spec

The scaffold command writes:

Concern Exact destination
Grant model src/models/pet.cr
Request schema src/schemas/pet_schema.cr
HTML CRUD controller src/controllers/pet_controller.cr
Index, show, new, edit, and shared form ECR src/views/pet/
Reversible Micrate SQL db/migrations/*_create_pets.sql
Model and request specs spec/models/pet_spec.cr, spec/controllers/pet_controller_spec.cr
Resource routes config/routes.cr

The generated migration contains -- +micrate Up and -- +micrate Down sections. amber database migrate applies the development database; setting AMBER_ENV=test applies the separate test database.

Amber CLI 2.0.6 generates an HTML schema that declares application/x-www-form-urlencoded. PetController binds it with schema :create, PetSchema and schema :update, PetSchema, then reads the request-local typed values through validated_as(PetSchema). Invalid input is stopped before the action and re-renders the ECR form with field errors. The controller does not manually construct and validate a second schema object. This is the released CLI 2.0.6 and framework 2.0.0-beta.5 path.

Run from: the application root — useful database maintenance commands.

Terminal
amber database status
amber database rollback
amber database redo
amber database seed

Released frontend and asset contract

The starter uses warm paper colors, faceted geometry, editorial type hierarchy, and compact status labels. It is authored entirely in the generated ECR and local CSS.

File: src/views/layouts/application.ecr — generated front-end entry point.

ECR template
<%= favicon_tag("images/favicon.svg") %>
<%= stylesheet_link_tag("stylesheets/app.css") %>
<%= javascript_importmap_tag(
  {"app" => "javascript/app.js"},
  preload: ["javascript/app.js"]
) %>
<script type="module">import "app";</script>

The visible page is src/views/home/index.ecr, the component layer is app/assets/stylesheets/app.css, and browser behavior begins in app/assets/javascript/app.js. See Import maps for adding local ESM modules without a Node.js runtime or bundler.

amber new compiles the first manifest before it returns. The generated boundary is:

Generated files and authored source — ownership reference:

File tree
my_app/
├── app/assets/                                  # authored; source control
│   ├── stylesheets/app.css
│   ├── javascript/app.js
│   ├── images/amber-crystal.svg
│   ├── images/favicon.svg
│   ├── fonts/.keep
│   └── files/.keep
├── config/assets.cr                             # runtime manifest resolver
├── public/
│   ├── assets/                                  # generated; gitignored
│   │   ├── manifest.json
│   │   └── ...fingerprinted files...
│   └── robots.txt                               # authored
└── src/views/layouts/application.ecr

Run from: the generated application root.

Terminal
amber assets build
amber assets check

amber watch rebuilds the manifest before application compilation and watches app/assets/**/* alongside Crystal and ECR source. Older applications can use the explicit scripts/build_assets.cr wrapper from the Asset Pipeline guide while adopting the same contract.

File: config/assets.cr — generated runtime resolver configuration.

Crystal
Amber::Assets.configure(
  manifest_path: "public/assets/manifest.json"
)

File: src/views/layouts/application.ecr — generated helper usage.

ECR template
<%= favicon_tag("images/favicon.svg") %>
<%= stylesheet_link_tag("stylesheets/app.css") %>
<%= javascript_importmap_tag(
  {"app" => "javascript/app.js"},
  preload: ["javascript/app.js"]
) %>
<script type="module">import "app";</script>

File: src/views/home/index.ecr — generated brand image usage.

ECR template
<%= image_tag("images/amber-crystal.svg", class: "starter-crystal", alt: "") %>

The generated stylesheet references ../images/amber-crystal.svg, proving that CSS URLs are rewritten as well as ECR helpers. Images, fonts, favicons, and arbitrary binaries receive the same content-addressed manifest treatment as CSS and JavaScript. User uploads do not; they remain persistent runtime data outside the authored tree.

Routes and request pipelines

File: config/routes.cr — generated pipeline and route ownership.

  • web includes errors, logging, sessions, flash, and CSRF.
  • static serves files under public/.
  • api is available for explicitly registered API routes.
  • / initially renders HomeController#index.
  • resources "/pets", PetController is added by the Pet scaffold.

Controller generation alone does not edit routes. Scaffold generation does, because its controller and views implement the complete resource contract.

Compile and browser contract

Run from: the generated application root.

Terminal
shards install
amber assets check
crystal spec
crystal build src/my_app.cr -o bin/my_app
amber watch

Open http://127.0.0.1:3000/ and http://127.0.0.1:3000/pets/new. The release test also submits that generated form, reads the stored Pet, edits it through _method=PATCH, and verifies the updated record.

The release gate runs amber assets build and amber assets check, starts the compiled application with its release directory read-only, and requests the fingerprinted CSS, JavaScript, image, and font URLs rendered from public/assets/manifest.json. It also verifies SRI, MIME types, immutable cache headers, gzip negotiation, and persisted Pet create/update behavior.

The supported web-template gate covers macOS, x86-64 Linux, and ARM64 Linux. Windows x86-64 must compile the same generated database-backed application in CI, but it does not yet have a CLI release archive. See Beta support for the platform boundary and Build a Pet Tracker for the complete first application.