v0.1.0 · AI-native

The declarative
fullstack language
for the AI era

Models, routes, SQL, auth, UI in one file. A grammar of 30 keywords small enough for LLMs to author, strict enough to compile to a single binary. Built-in MCP server so AI tools read the spec directly.

Traditional · 11 deps

import express, prisma
import passport, csurf, bcrypt
import { engine } from ejs

// routes/tasks.js
app.post('/tasks', auth, csrf,
  async (req, res) => {
    const task = await prisma
      .task.create({ data: {...} });
    res.redirect('/tasks');
  }
);

// schema.prisma, .env,
// session config, views/,
// validators/, middlewares/

Kilnx · 0 deps

model task
  title: text required
  done: bool default false
  owner: user

action /tasks method POST requires auth
  validate task
  query: INSERT INTO task ...
  redirect /tasks

// That's it. Auth, CSRF,
// validation, DB migration,
// session: built in.
~480 LOC across 12 files  →  18 LOC in 1 file

Same app. Less everything.

A task manager with auth, CRUD, and real-time updates. One requires a stack. The other requires Kilnx.

Traditional Stack
Express + Prisma + EJS + Passport ~12 files, ~480 lines
package.json
"express", "prisma", "@prisma/client",
"ejs", "passport", "passport-local",
"express-session", "csurf", "bcrypt",
"express-validator", "connect-flash"
// 11 dependencies

schema.prisma
model Task {
  id        Int      @id @default(autoincrement())
  title     String
  done      Boolean  @default(false)
  createdAt DateTime @default(now())
  userId    Int
  user      User     @relation(...)
}

routes/tasks.js
const router = express.Router()
router.get('/', ensureAuth, async (req, res) => {
  const tasks = await prisma.task.findMany({
    where: { userId: req.user.id },
    orderBy: { createdAt: 'desc' }
  })
  res.render('tasks/index', { tasks })
})
// + POST, PUT, DELETE handlers
// + validation middleware
// + error handling

// + views/tasks/index.ejs
// + views/layout.ejs
// + config/passport.js
// + middleware/auth.js
// + middleware/csrf.js
// + prisma/migrations/...
// + app.js (server setup)
Kilnx
app.kilnx 1 file, 40 lines
config
  database: env DATABASE_URL default "sqlite://app.db"
  port: 8080
  secret: env SECRET_KEY required

model task
  title: text required
  done: bool default false
  owner: user required
  created: timestamp auto

auth
  table: user
  identity: email
  password: password
  login: /login
  after login: /tasks

page /tasks requires auth
  query tasks: SELECT id, title, done FROM task
               WHERE owner = :current_user.id
               ORDER BY created DESC
               paginate 20
  html
    <h1>My Tasks</h1>
    {{each tasks}}
    <div>
      <span>{title}</span>
      <button hx-post="/tasks/{id}/toggle">Toggle</button>
    </div>
    {{end}}

action /tasks/create method POST requires auth
  validate task
  query: INSERT INTO task (title, owner)
         VALUES (:title, :current_user.id)
  redirect /tasks

Dependencies

11 0

Files

12+ 1

Lines of code

~480 40

Config files

5 0

Everything you need,
nothing you don't

30 keywords replace an entire stack, and the grammar fits in an LLM context window. Models, pages, actions, auth, jobs, emails, websockets, API endpoints.

SQL First-Class

No ORM, no query builder. Write SQL inline with parameter binding. JOINs, aggregates, subqueries. Your database is a feature, not an afterthought.

HTML Native Output

HTML is the return type. Pages, fragments, and layouts compose naturally with {{each}}, {{if}}, and {field} interpolation. No template engine bolted on.

htmx-Aware

Fragments, SSE streams, WebSockets, and broadcast are built-in keywords. Partial HTML updates without writing a single line of JavaScript.

Single Binary

Compiles to one ~15MB executable with SQLite, bcrypt, and htmx.js embedded. No runtime, no dependencies, no node_modules. Copy and run.

Security by Default

CSRF tokens auto-injected in forms. SQL injection prevented by parameterized queries. XSS blocked by auto-escaping. Bcrypt password hashing built-in.

AI-Native

A grammar that fits in any context window. Built-in MCP server exposes the spec, keywords, and examples to AI tools. LLMs write valid Kilnx on the first try because there are no surprises to guess at.

30 keywords

Python has 35 keywords and does none of this without importing libraries. JavaScript has 64. Java has 67. Kilnx has 30 and delivers a complete web app from database to browser.

kilnx explain
$ kilnx explain

Click a keyword to explore the language.

Less moving parts, same result

For the 80% use case (forms, dashboards, CRUDs with auth), Kilnx does more with less.

Kilnx Django Rails Next.js Phoenix
Dependencies 0 50+ 30+ 100+ 20+
Blog with auth (LOC) 94 ~500 ~400 ~1000 ~350
Compiled binary Yes (~15MB) No No No Yes (BEAM)
Built-in auth 6 lines Yes Devise gem No phx.gen.auth
Built-in jobs Yes Celery Sidekiq No Oban
Built-in testing Same file Django test RSpec Jest/Vitest ExUnit
Realtime (SSE/WS) Built-in Channels ActionCable Manual LiveView
Learning time ~1 hour ~40 hours ~40 hours ~30 hours ~50 hours

11 design
principles

htmx completed HTML. Kilnx gives htmx the backend it assumes already exists: raw declarations go in, a solid binary comes out. Makes the backend as simple as the problem demands, not as complex as the tools allow.

00The complexity is the tool's fault, not the problem's
01Zero decisions before the first useful line
02SQL is first-class citizen
03HTML is the native output
04Declarative first, imperative when necessary
05One file can be a complete app
06The binary is the deploy
07Fragments are first-class
08Security is default, not opt-in
09Zero dependencies for the user
10htmx awareness without htmx coupling

Ready to build?

Star the repo, join the community, or start building right now.

Get Started Deploy on Railway