Philippe Marschall pointed me to the Arc Challenge:

Write a program that causes the url said (e.g. http://localhost:port/said) to produce a page with an input field and a submit button. When the submit button is pressed, that should produce a second page with a single link saying "click here." When that is clicked it should lead to a third page that says "you said: ..." where ... is whatever the user typed in the original input field. The third page must only show what the user actually typed. I.e. the value entered in the input field must not be passed in the url, or it would be possible to change the behavior of the final page by editing the url.

The solution in Arc consists of 23 parse tree nodes:

(defop said req (aform [w/link (pr "you said: " (arg _ "foo")) (pr "click here")] (input "foo") (submit)))

My solution in Seaside only requires 14 parse tree nodes:

| something |

something := self request: 'Say something' .

self inform: 'Click here' .

self inform: something

The running application can be tested below:

Say something

Obviously people will argue that I didn’t exactly play with the rules. In the second step I don’t use a link, but a submit button. You are right. Unfortunately Seaside doesn’t provide a ready-made page that uses a link to proceed. However, and in my opinion this is far more important, the data is not passed through hidden post fields or through the URL. There is no way to fake the output of the last step.

Another important point is readability. Read the Smalltalk code from top to bottom. I reads like english prosa and it simply does what it says. Without bells and whistles. And – does your framework support the back button as well? Does it also prevent you from XSS attacks?