HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
weavejester
hiccup
Clojure2010–2025
weavejester / hiccup

hiccup

Fast library for rendering HTML in Clojure

59Distinct people
64Mentions
1Explicit recommenders
2.9KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Fast library for rendering HTML in Clojure

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

Do you have a github repo for your project ? Or somewhere where I can take a look at the code ? I was hoping to find the time to write something similar in Clojure (a lisp…

siscia used a recommendation phrase. One indexed comment matches. This is a phrase match, not a verdict.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 4:01:40 AM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year64 dated mentions

Observed mentions: 2010-04-26 15:18:06 UTC to 2025-12-03 19:46:10 UTC.

0369122010-01-01 00:00:00 UTC to 2011-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20102011-01-01 00:00:00 UTC to 2012-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2012-01-01 00:00:00 UTC to 2013-01-01 00:00:00 UTC (exclusive): 11 mentions; 0 submissions, 11 comments2013-01-01 00:00:00 UTC to 2014-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2014-01-01 00:00:00 UTC to 2015-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20172018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 6 mentions; 0 submissions, 6 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 7 mentions; 0 submissions, 7 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 6 mentions; 0 submissions, 6 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 1 mentions; 1 submissions, 0 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 6 mentions; 0 submissions, 6 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments2025

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20102010-01-01 00:00:00 UTC2011-01-01 00:00:00 UTC202
20112011-01-01 00:00:00 UTC2012-01-01 00:00:00 UTC101
20122012-01-01 00:00:00 UTC2013-01-01 00:00:00 UTC11011
20132013-01-01 00:00:00 UTC2014-01-01 00:00:00 UTC404
20142014-01-01 00:00:00 UTC2015-01-01 00:00:00 UTC303
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC404
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC101
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC202
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC404
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC606
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC707
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC606
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC110
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC606
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC404
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC211

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
Hiccup Hiccup is a library for representing HTML in Clojure. It uses vectors to represent elements, and maps to represent an element's attributes. Install Add the following dependency to your deps.edn file: hiccup/hiccup {:mvn/version "2.0.0"} Or to your Leiningen project.clj file: [hiccup "2.0.0"] Documentation Wiki API Docs Syntax Here is a basic example of Hiccup syntax: user=> (require '[hiccup2.core :as h]) nil user=> (str (h/html [:span {:class "foo"} "bar"])) "<span class=\"foo\">bar</span>" The first element of the vector is used as the element name. The second attribute can optionally be a map, in which case it is used to supply the element's attributes. Every other element is considered part of the tag's body. Hiccup is intelligent enough to render different HTML elements in different ways, in order to accommodate browser quirks: user=> (str (h/html [:script])) "<script></script>" user=> (str (h/html [:p])) "<p />" And provides a CSS-like shortcut for denoting id and class attributes: user=> (str (h/html [:div#foo.bar.baz "bang"])) "<div id=\"foo\" class=\"bar baz\">bang</div>" If the body of the element is a seq, its contents will be expanded out into the element body. This makes working with forms like map and for more convenient: user=> (str (h/html [:ul (for [x (range 1 4)] [:li x])])) "<ul><li>1</li><li>2</li><li>3</li></ul>" Strings are automatically escaped: user=> (str (h/html [:p "Tags in HTML are written with <>"])) "<p>Tags in HTML are written with &lt;&gt;</p>" To bypass this, use the hiccup2.core/raw function: user=> (str (h/html [:p (h/raw "Hello <em>World</em>")])) "<p>Hello <em>World</em></p>" This can also be used for doctype declarations: user=> (str (h/html (h/raw "<!DOCTYPE html>") [:html {:lang "en"}])) "<!DOCTYPE html><html lang=\"en\"></html>" Differences between Hiccup 1 and 2 In brief: Hiccup 1 doesn't escape strings by default, while Hiccup 2 does. They occupy different namespaces to ensure backward compatibility. In Hiccup 1, you use the h function to escape a string - that is, ensure that unsafe characters like <, > and & are converted into their equivalent entity codes: (h1/html [:div "Username: " (h1/h username)]) In Hiccup 2 strings are escaped automatically, but the return value from the html macro is a RawString, rather than a String. This ensures that the html macro can still be nested. (str (h2/html [:div "Username: " username])) It's recommended to use Hiccup 2 where possible, particularly if your app handles user data. Use of the non-core namespaces, such as hiccup.page, should be avoided with Hiccup 2. License Copyright © 2025 James Reeves Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Read the full README on GitHub

What Hacker News says

11 sources
In dōmo: Markup, style, and code in one language
I enjoy using Hiccup more than any template engine I've used previously. Before I met (Clojure and) Hiccup[1], I would have said the same regarding Coffeekup[2]. But what's really amazing is when you combine Hiccup with Enlive[3]. Enlive can give you a headache when you first start working with it, but then there's an almost magical "aha!" moment, and not long after that you'll never want to look back. By "combine" I mean using Hiccup and metadata from your db (or whatever) to generate empty, logic-less views and then using Enlive to bind in your data. Combine those steps with your own macros and HOFs, look for some choice places to memoize function calls, and now you're cooking with gas. [1] https://github.com/weavejester/hiccup [2] https://github.com/mauricemach/coffeekup [3] https://github.com/cgrand/enlive
In The Lesser Known Contributors Who Are Trying To Make PHP Good Again
I think that this is an interesting experiment, and reminds me of Clojure's hiccup[1] library. In hiccup, you model html to be rendered as nested vectors and maps, such that <span class="foo">bar</span> becomes (html [:span {:class "foo"} "bar"]) Where this is a real win is when you realize that it's just data: (html [:ol (for [x (range 1 4)] [:li x])]) Lisps are well suited to model html. [1] https://github.com/weavejester/hiccup
In Lisp-like html as a replacement to bbcode/markup/textile
>>How do you modify small chunks of templates and then check how it looks in the browser without leaving your editor > https://github.com/weavejester/hiccup hiccup is just another approach to do html generation. This style of html generation is common in lisps - Racket uses it as well. hiccup(or this genre of templating) can be conveniently implemented in Ruby, or any language for that matter. I prefer explicit templates(particularly slim). Additionally, I don't see what I gain by the fact that I can potentially change my hiccup input, run it in the repl and see what html it produces. If the library is well tested, I won't have a need to check if it is producing html corresponding to the input list. > Lisp is _amazing_ at processing lists, so this style of programming plays to the languages strengths. I don't think Lisp is amazing at pro
Read the rest
cessing list is the reason behind this style of programming - Ruby has excellent seq abstractions(from the top of my head, I can't think of a list abstraction/method that lisp supports that Ruby doesn't). The fact that this style of programming is common is due to Lisp's s-expr syntax. > But there is a fairly old idea that when you are working on code, it should be against a running version. Smalltalk was the ultimate expression of that, (where there is no difference between editor and app), but the typical way that a lisper works is the next best thing. I still see only one thing(emacs-slime drops to the debugger if evaluation fails) that lisp has extra of. Ruby, Python et al have the same feedback cycle. The things that can be interactively tested in Lisp can most probably be tested Ruby. You wrote a function which takes a sentence and qualifies it as happy/sad - irrespective of whether it's lisp or Ruby, you drop in the repl and feed it your input, or you write tests and run them. You changed your app to allow facebook login, you either interactively run it in the browser or write a test.
In How To Build And Deploy Common Lisp In The Cloud (And Comparing Rails)
>How do you modify small chunks of templates and then check how it looks in the browser without leaving your editor https://github.com/weavejester/hiccup >and how is that a property of lisp? The "lisp way" is to convert the problem into something solvable by lists, then convert those lists into whatever they need to be. Lisp is _amazing_ at processing lists, so this style of programming plays to the languages strengths. >Also, I was pointing out that you don't get to define REPL to comply with what you think it should mean. I didn't say anything about interactive development. Granted. But there is a fairly old idea that when you are working on code, it should be against a running version. Smalltalk was the ultimate expression of that, (where there is no difference between editor and app), but the typical way that a lisper works is the nex
Read the rest
t best thing. When you are used to working that way, it is hard to go back, since the feedback cycle is just so tight, and exploratory coding is so simple.
In How To Build And Deploy Common Lisp In The Cloud (And Comparing Rails)

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.