Jun 20, 2026: IHP 1.6 is out now!

The Haskell Framework for Agentic Engineering

Your agent writes the code. The compiler proves it works. Typed SQL, schema-generated records and compile-checked HSX turn plausible-looking AI output into a build error — before it ever runs.
-- Your agent wrote this:
posts <- sqlQueryTyped [typedSql|
    SELECT id, title, publish_date FROM posts
|]
error: [GHC-39584]
  • typedSql: prepare failed:
    ERROR:  column "publish_date" does not exist
LINE 1:  SELECT id, title, publish_date FROM posts
                           ^

This never reaches production. typedSql asks your Postgres to describe the query while your code is still compiling.

Code review doesn't scale. Types do.

An agent produces more code in an afternoon than a team can review in a week. The bottleneck was never typing speed — it's knowing the code is correct. In most stacks the answer is "run it and find out." In IHP the answer is: it doesn't compile.

Typed SQL

Every query is checked against your real Postgres schema at compile time. A hallucinated column is a build error, not a 3am page.

learn more

Generated from your schema

Your schema file is the single source of truth. Records, ids and enums are generated from it, so your agent's code can't drift from your database.

learn more

Compile-checked views & routes

HSX parses your HTML at compile time. The routes DSL validates every path capture and query parameter against your action types.

learn more

Ground truth, not guesswork

A Hoogle server runs on every project by default, indexing every package in your flake. Your agent looks up real type signatures instead of inventing them.

learn more
$ ihp-new blog

blog/
├── AGENTS.md              # house rules your agent reads first
├── CLAUDE.md              # → AGENTS.md
├── .claude/
│   └── launch.json        # Claude Code preview, auto-port
├── Application/Schema.sql
└── flake.nix

Agent-ready out of the box

Conventions, committed. An AGENTS.md ships with the project: use typed SQL over raw SQL, stamp migrations with a real timestamp, and verify before handing off.

Claude Code preview, already wired. The dev server honors the PORT environment variable, so the preview picks a free port and IHP binds exactly that one instead of silently drifting to another.

Typechecks headless. Compile-time SQL checking starts a temporary Postgres on demand, so it still works in agent workspaces where the dev server isn't running.

One command to verify. Run nix flake check --impure — it builds, typechecks and runs the suite, the handoff gate before you even look at a diff.

See it in action

A walkthrough of building an IHP app end to end — clicking together the schema, generating the controller and views, and watching the dev server reload as the code changes.

Everything here is the same loop your agent works in.

Featured on heise.de

Halved latency with the new database layer

Read the full article on heise.de
heise online

Recognized by G2 reviewers

G2 High Performer
9.6
Overall
8.9
Ease of Use
9.6
Support
Read reviews

What do our users say about us?

I love that it's based on Haskell, yet feels familiar like Rails: you get all of the superpowers of the Haskell compiler, which helps you avoid many classes of errors, and it's combined with the pragmatism of Rails which allows you to ship code quickly. I'm not a Haskell expert by any means, but I was able to build multiple prototypes within a week, all of which were much higher quality than I expected them to be.
John Yoder
VP Engineering, AppFolio
IHP is a fantastic framework that has rekindled my love for programming. It is beginner-friendly for those with little or no experience learning Haskell. It is easy to learn and use. It has a built-in browser-based IDE that provides essential features, such as a schema editor for database management and a code generator for rapid development. It has a very constructive and friendly community. Most importantly, however, it is fun to use.
Joshua Obritsch
Software Engineer
IHP is the best web framework experience I have had.
Henry Lambert
Founder, Comhlan Ltd.
IHP is ridiculously good. I hope it makes Haskell a bigger part of the web dev industry because wow
James Foster
@ratherforky
I think in Open Source projects two things are important among other: community and documentation. I found them in IHP.
Max Bertinetti
Web Developer
This is *very* impressive work. A whole new Haskell web framework based on Warp server, with a non-TH ORM and type-safe templating framework. 🚀
Stephen Diehl
CTO & Founder
Dude... it's the coolest web framework I've used.... I think the people who try it, love it. I say that as someone coming from ASP.NET Core and a little bit of the F# ones (Giraffe and Saturn). IHP blows everything I've seen out of the water.
Eduardo Cavazos
Software Developer
This is a really impressive project, super excited to try it. All this time I've been doing Haskell web development I've been wishing for features like an admin UI and all the other things rails/django have had for a long time
Avi Press
CEO, Scarf
The more I look at IHP, the more I think this is Haskell's killer framework. Really excellent work.
Will Ricketts
Software Engineer
Amazed at the quality of documentation of IHP. They are doing a splendid job
Geoffrey Huntley
Principal Developer Advocate, Gitpod
If you've enjoyed the safety and pleasureable development experience on developing in #elmlang, and enjoyed the power, speed and of server-side rendered front-end with #phoenix_liveview, here comes #ihp (Integrated Haskell Platform) @digitallyinduce
Yeong Sheng (永胜)
Software Developer
IHP is supposed to become the Django/Rails/Phoenix of Haskell.

I’ve been using Django professionally for since 2013, but have started using IHP a couple of weeks ago. It’s still quite early but with surprisingly few rough edges, i.e. the developer ergonomics are much better than I expected. It has great documentation that is improving rapidly (as opposed to many other Haskell libraries, which provide little more than API docs or even just the typed function definitions) and offers a refreshing take on database management and migrations.
Hendrik Richter
CEO, evers-internet

Instant Live Reloading

While haskell is a compiled language, the built-in dev server automatically reloads your code changes using the fastest way possible.

Changes are reflected instantly. Just like good old PHP.

You don't have to write Haskell to benefit from it

IHP is written in Haskell — a language with a type system strong enough that Mercury and Standard Chartered run banking infrastructure on it. That used to be a trade-off: more guarantees, less familiarity.

With an agent at the keyboard it stops being a trade-off. Haskell tells your agent it's wrong immediately and precisely, in a way Python and TypeScript can't. The stricter the language, the tighter the loop.

You review behaviour. The compiler reviews the code.

Star

-- Make a password hash
hash <- hashPassword "hunter2"

-- Set values
let user = newRecord @User
        |> set #email "someone@example.com"
        |> set #passwordHash hash

-- Insert it into the DB
createRecord user
action UsersAction = do

    -- Fetch 10 users ordered by firstname
    users <- query @User
        |> orderBy #firstname
        |> limit 10
        |> fetch

    render IndexView { .. }
-- The autoRefresh keyword makes the action realtime
-- No app-specific JS needed
--                        ↘↘↘
action MessagesAction = autoRefresh do
    messages <- query @Message
        |> orderBy #createdAt
        |> fetch

    render IndexView { .. }
Learn more about IHP Auto Refresh

Ship AI features without a JavaScript frontend

ihp-openai gives you streaming completions, typed function calling and structured output. When a stream drops it resumes from the partial response, so your user never sees the retry.

Write each token into a Postgres column and Auto Refresh does the rest — it diffs the page server-side and pushes only what changed over a WebSocket. No client-side state, no streaming endpoint, no JavaScript.

Long-running work goes to background jobs backed by Postgres LISTEN/NOTIFY, with retries and scheduling built in.

Auto Refresh Background Jobs

-- Each token lands in Postgres as it arrives
streamCompletion config request (pure ()) \chunk ->
    forEach chunk.choices \choice ->
        forEach choice.delta.content \token ->
            sqlExecTyped [typedSql|
                UPDATE answers SET body = body || ${token}
                WHERE id = ${answerId}
            |]

-- The view is already live. No JavaScript needed.
action ShowAnswerAction { answerId } = autoRefresh do
    answer <- fetch answerId
    render ShowView { .. }

Design your Tables with the Schema Designer

IHP is a database centric web framework. We introspect your database schema to provide type-safe APIs and query builders.

You don't have to be a database expert to use IHP, with the Schema Designer you quickly click together your data structures.

If you like your code editor more, you can always manually edit the SQL files.

Sophisticated Forms

Stop dealing with repetitive form HTML code. IHP brings you a sophisticated but simple form engine that takes care of the HTML and validation logic.

instance View NewView where
    html NewView { .. } = [hsx|
        <h1>New Comment</h1>

        {renderForm comment}
    |]

renderForm comment = formFor comment [hsx|
    {hiddenField #threadId}

    <!-- Labels + Validation Results are taken care of -->
    {textareaField #body}

    {submitButton}
|]
instance View NewView where
    html NewView { .. } = [hsx|
        <h1>New Comment</h1>

        {renderForm comment}
    |]

renderForm comment = formFor comment [hsx|
    {hiddenField #threadId}

    {(textareaField #body) {
        fieldLabel = "Your Comment:",
        helpText = "You can use markdown here."
    }}

    <p>
        <!-- Use any HTML inside your forms -->
        Please double check your comment
        for spelling mistakes.
    </p>

    {submitButton}
|]
action CreateCommentAction = do
    let comment = newRecord @Comment

    comment
        |> fill @["body", "threadId"]
        |> set #userId currentUserId

        -- Actual validation here
        |> validateField #body nonEmpty
        |> validateField #threadId nonEmpty

        |> ifValid \case
            -- Validation Failed -> Render form + errors
            Left comment -> render NewView { .. }

            -- Validation Good
            Right comment -> do

                -- Insert comment to DB
                comment <- comment |> createRecord

                let commentId = get #id comment

                -- Redirect to comment
                redirectTo ShowCommentAction { commentId }

Try out what the future of software engineering feels like

Join our Community Today!

Stay up to date on Twitter

Follow digitally induced on Twitter to be first to know about news on IHP.

Connect with other Devs on Slack

If you're new to haskell the IHP Slack is a great place to get help.

Star IHP on GitHub

Curious about the code? Check out the IHP repository on GitHub.

Not yet ready to Code?

Stay up to date with our latest features and the new releases by signing up for our newsletter!