Getting started

Install the toolchain, create a project, serve it

# Getting started

## The toolchain

Askr needs Free Pascal. It builds and passes its full test suite on **3.2.2**
and **3.3.1 trunk** — keeping both green is how the project finds out
whether a compiler limitation is gone or has only moved.

```sh
# Debian, Ubuntu
apt install fp-compiler fp-units-rtl fp-units-fcl fp-units-net

# macOS
brew install fpc
```

> **Not `apt install fpc`.** That metapackage pulls in the GTK2,
> multimedia and graphics unit packages and their `-dev` dependencies —
> libvlc, Mesa, X11 headers. Measured on Ubuntu 24.04: **326 packages
> against 11.** Askr uses the compiler, the RTL, the FCL (`Classes`,
> `SyncObjs`, `TypInfo`) and `netdb` from the networking units, and
> nothing else. If a unit does turn out to be missing, fpc names it —
> `Can't find unit X` — and that is one package to add, not three hundred
> to remove.

If `fpc` is on `PATH` it is used. Otherwise the framework's own build script
builds and uses the Docker image in `tools/Dockerfile.fpc`. Point
`ASKR_FPC` at a specific compiler to override both.

> The official `freepascal/fpc` image is musl-based and does not link
> against `cthreads`. Do not use it.

Optional, per feature:

| Library | Needed for |
|---|---|
| `libpq` | Postgres |
| `libmariadb3` / `mariadb-connector-c` | MySQL — this is the binding, not `libmysqlclient` |
| `libsqlite3` | SQLite |
| `libssl` / `libcrypto` (OpenSSL 3) | HTTPS, STARTTLS, the HTTP client over TLS |
| GTK3 + WebKitGTK | The Linux desktop shell |

All of them are loaded with `dlopen` at first use. The binary starts on a
machine that has none of them; you only pay for what you touch.

> **On macOS you must install OpenSSL yourself** (`brew install openssl@3`).
> The system `libssl` is LibreSSL, and Apple blocks `dlopen` against it from
> third-party binaries — the process dies with "loading libcrypto in an
> unsafe way". There is no way around it.

## Build the CLI

From a checkout of the framework:

```sh
./askr cli
```

> **Two things are called `askr`.** `./askr` in a checkout of the framework
> is the framework's own build script — it builds and tests Askr itself, and
> has commands like `./askr test`, `./askr check` and `./askr tls:certs`.
> `askr` on your `PATH` is the CLI you use in a project. This documentation
> writes `./askr` for the first and plain `askr` for the second.

That builds `.build/bin/askr`. Put it on your `PATH` and tell it where the
framework lives:

```sh
export PATH="/path/to/askrcode/.build/bin:$PATH"
export ASKR_HOME="/path/to/askrcode"
```

## A new project

```sh
askr new shop
cd shop
askr serve
```

`askr new` asks whether the project needs sign-in. Say yes and you get
`/login`, `/register` and `/reset-password` wired up — see
[Authentication](auth.md). `--auth` and `--no-auth` answer for a script.

### Cloning a project instead

Someone else's Askr project does not carry the framework with it. It
carries `askr.lock`, which names the release it was built against:

```sh
git clone …
cd shop
askr install              # fetch that release into ~/.askr/pkg
(cd frontend && npm install)
askr build
```

`askr install` also points `@askrcode/lauf` at the matching version, so
the two halves of a release cannot drift apart. See
[Versions](versions.md).

`askr serve` builds the app and starts it behind a dev server that watches
your source and rebuilds on change. The loop is measured at **247 ms** on
the reference machine, against a 300 ms budget.

Open `http://127.0.0.1:8080`. You get a welcome page that ships with the
framework: no npm, no network, no files beside the binary. It shows the
arena for the worker that served it, which is the shortest possible
demonstration of what makes Askr different.

## What you got

```
shop/
  askr.toml                  project settings; the app reads them too
  .env                       secrets; never committed
  .env.example               the list of what a new developer must fill in
  app.lpr                    the program: wiring, routes, server
  app/
    Http/
      App.Http.HomeController.pas
  database/
    App.Migrations.pas       generated index; do not edit
    App.Seeders.pas          generated index; do not edit
  frontend/                  Vite + Svelte 5 + Inertia
```

A new project has **sessions, CSRF protection and authentication wired in
from the first request**. A POST without a valid token answers 419 before
it reaches your handler. That is not something you switch on; it is the
default, and turning it off is the deliberate act.

## Your first route

`app.lpr` holds the wiring. Routes are registered there:

```pascal
R.Get('/', Home.Index);
R.Get('/demo', Home.Demo);
```

The handler lives in a controller:

```pascal
function THomeController.Index(Req: TRequest): TResponse;
begin
  Result := RespondText('hello');
end;
```

Add a route, save, and the dev server rebuilds. See [Routing](routing.md).

## Your first table

```sh
askr make model Post --migration
```

That writes a model in `app/Models/` and a migration in `database/`. The
database is in `.env`, and a new project starts on SQLite, which needs no
server:

```
DATABASE_URL=sqlite:shop.db
```

**MySQL is the database Askr prefers** for everything past the first
afternoon, and `askr new shop --database=mysql` starts there instead:

```
DATABASE_URL=mysql://root@127.0.0.1:3306/shop
TEST_DATABASE_URL=mysql://root@127.0.0.1:3306/shop_test
```

The tests get a database of their own, where each test is rolled back --
see [the sandbox](testing.md). Make the two databases once; askr does not
own your server:

```sh
mysql -uroot -e "CREATE DATABASE shop CHARACTER SET utf8mb4; CREATE DATABASE shop_test CHARACTER SET utf8mb4"
```

Postgres works as well as either, and is a line to uncomment in `.env`.

Then:

```sh
askr migrate
askr db:table posts
```

`askr migrate` cannot be run by the tool. Migrations are Pascal code
compiled into your binary, so the tool asks the binary to run them. That is
why you must `askr build` (or `askr serve`) before a migration is visible.

See [Migrations](migrations.md) and [Models](models.md).

## The frontend

Inertia and Svelte 5 are set up but not installed:

```sh
cd frontend && npm install
```

Restart with `askr serve` and `/demo` becomes a Svelte page. You can also
ignore all of it: Askr serves HTML, JSON and files without a frontend build
step. See [Inertia and Svelte](inertia.md).

## Where to go next

- [The arena](arena.md) — read this before you write code that outlives a
  request. It is the one rule that is not like other frameworks.
- [The CLI](cli.md) — every command.
- [Configuration](configuration.md) — where values come from and which
  source wins.