Webtalk is a web-implementation of HyperTalk. That doesn't mean you have to be online to run it. You can download it and run it from a computer with no internet connection.
So what does webtalk do?
Webtalk is loosely based on the HyperTalk scripting language, and the goal is to be compatible in most major respects. There are additions to it and perhaps things missing from it. The boring bit is I'm not implying it's fit for any particular purpose, and there's no guarantees implied or otherwise about how it might run on your system. (Being based on Javascript and CSS, it heavily relies on what your browser is capable of).
The point of it is it's a programming language that's easy to type and understand.
For example, If I wanted to output the current date in javascript, I'd have to type:
Code:
const now = new Date();
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
const dayName = days[now.getDay()];
const dateTimeString = now.toLocaleString();
document.getElementById('datetime').textContent = `${dayName}, ${dateTimeString}`;
Result:
And although to do that in Python is simpler, it's not as readable:
Code:
from datetime import datetime
now = datetime.now()
formatted = now.strftime("%A, %d/%m/%Y, %H:%M:%S")
print(formatted)
Which again, gives us this:
Result:
Whereas, if I want to do that in HyperTalk, I'd be able to use:
Code:
put item 1 of the long date & "," && the date & "," && the time
Result:
However, the great thing about hyperTalk (and webtalk), is that it can also be quite flexible:
put item 1 of the long date & "," && dateFormat(the dateitems, "%d/%m/%Y") & "," && the time
HyperTalk script
HyperTalk was the programming language created in 1987 by Dan Winkler, and used in the HyperCard application, created by Bill Atkinson. Creating programs in HyperTalk was known as "scripting". HyperTalk scripts were much more similar to written English than many languages available at the time.
Webtalk script
A simple example of webtalk scripting:
This gives you an idea of what I'm aiming for here, to have something that is platform-agnostic which is capable of running HyperTalk scripts.
I'm trying to give a comparable set of features that were available in Hypertalk, but in Webtalk - so they are available to everyone. As such, there won't be specific Mac-only, Windows-only or Linux-only features implemented on this project. If I add a feature, it will be supported across all platforms.
Current progress:
The current documentation containing the release notes are here, as a PDF
You might also want to read the license agreement on that last page of the documentation too.
Download
You can download a copy of webtalk, (current version), from here. You don't need anything special to run it. Just a recent browser (if you are using Safari, needs to be version 17 or above)
Alternatively, if you prefer, you can try it as an online live demo here. You might also want to check out the testing pages, which give you a list of commands and handlers that are currently implemented.
Overview
A project overview (text file) is also available, which covers how this all works at a quick glance.
I should really mention, you can load JSON stacks with:
load stack "" -- if it can't find the file, it will ask you
Recent additions:
v141
Having now finished adding shapes for a while, I have implemented an inspector. At the moment, this is only used to get what properties you might have applied to an object. I will modify this in future so that you can also set properties with it as well. You can invoke the inspector either by double-clicking an object with the edit tool / edit mode, or pressing ctrl i when you have an object selected with resize handles shown.
v142
Added additional field tools, modified the tool icons (now use SVG images instead of emojis).
v143
Updated the "Testing" page to show all the current syntax that webtalk can handle. I also added a "Test Pages" button on the tools palette, so it's easy to get to for quick reference (handy if you want to look up how to do something).
v144
Made the script editor window resizable, tweaked the format button in the script editor, and made the webtalk online demo work for mobile devices.
Well, works on Android at least.
On iOS, I can't hold down my finger on an object to invoke the popup menu (it currently tries to select the text of the button, so I have to run the command to edit the script via the message box).
v145
Fixed a few auto-correct issues for iOS and Android in the script editor. Made the "Run tests" button on the "Testing page" reset before each click, and added a new isuppercase() function. (see documentation).
v146
You can now create an image object using:
create image "imagename"
Or you can use the "Add Image" icon on the Tools palette.
You can currently set the image filename (the actual image used in the image object) using:
set the filename of image "imagename" to "filename.png"
If you proportionally scale the image, or even resize it so it's distorted, this does not affect the data of the image object in any way.
v147
Too many changes to list here. Please see the documentation. :)
v148
Major fix to the object model renaming, and continued work on the inspector.
v149
Most notable fix is the addition of the "video" button on the tools palette (now supports player objects).

Please see the documentation for more info.
v150
Quick overview of changes: Fixes to the script editor involving comments, you can now move a selected object around the card using the arrow keys in edit mode, the card now detects the arrowkeys, added support for custom functions, added 'clear message box' function, added more shapes to the tools palette.
v151
Expanded upon the key events. (keydown, keyup, rawkeydown, rawkeyup, and a new one - keyheld) Please read page 54 of the documentation.
v152
I've added support for the pendingmessages and webtalk now also supports the 'move' command. Please see the documentation for further details (page 56).
v153
I added the 'spin' command. (made sense since we have a move command). I also corrected a rename issue with the inspector (which I'll detail more about in the documentation).
v154
Today I expanded the play note range (note frequencies in documentation), and I also expanded on sending function handlers to other objects.
on mousedown
send playSound("E",120) to this card in 400 milliseconds
end mousedown"
This will send that command, along with it's variables, to the playSound function handler in the card, after 400 milliseconds. (non-blocking). In your card script, all you then need is:
on playSound thenote,theTempo
put thenote into tNote
put theTempo into tTempo
play tNote tempo tTempo
end playSound"
musical-note-btns.json
v155
Expanded upon the put, and lines function... It can now support a lot more 'fuzzyness' - I'll detail that in the release notes. I'm now making test stacks as that's the best way to find what webtalk is missing.
count-test.json
See the 'Example Stacks' on the left-navigation panel.
v156
I've added a HyperTalk-Extender module. The HyperTalk-Extender (hte), is a way to add new functions to the interpreter, so that they are available to any stack.
The idea is you'd add them to hypertalk-extender.js -- here's one I added to line 28 to test it:
// myCommand sample script
HyperTalkExtender.registerScript('myCommand', [
'get item 1 of the long date',
'put it into tResult'
]);
Then, to run it, create a new button and use this script:
on mousedown
get hte_myCommand -- prefix all HyperTalk-Extender commands with "hte_"
put it
end mousedown
The output from this is:
(This would vary depending on the day of the week).
This way, people can write their own scripts which can be called from any other stack, just by customising the hypertalk-extender.js
v157
Added variable line heights to fields, with the commands:
set the lineheight of field "a" to 32
set the lineheight of line 1 of field "a" to 10
lineheight.json
As always, more information can be found in the documentation.
v158
Added the baseURL function:
put the baseURL
Outputs the current address the webtalk interpreter is loading from:
https://www.tsites.co.uk/sites/webtalk/progress/live-demo/
or
file:///home/user/webtalk/index.html
..for example. This might be handy for finding out if you are in an online instance of the interpreter or in a locally-downloaded copy.
v159
Webtalk now supports some font commands and functions:
put the fontNames
start using font "myfont.ttf"
put the lastLoadedFont -- returns the internal font name of the last loaded font
set the textFont of field "test" to "myfont Regular"
stop using font "myfont Regular"
fonts.json
v160
Added fixes for the ask dialog, the "if exists" function, fixes to the convert command to handle the short date better, and added the combine function as a synonym of the join function. Please see the documentation for further details.
object-exists.json
put-field-test.json
v161
A few fixes to the way the inspector sets some properties, using the "ask list" to choose fonts now, and a bit of code cleanup. Nothing too major. I also added the ability to exit a handler:
on mousedown
clear message box
put "a"
put "b"
exit mousedown
put "c" -- should never get to this point
end mousedown
exit-handlername.json
v162
Added a couple more features to Webtalk today. You can now use:
put isOdd("9") -- returns true if the number is odd, false if even
I also added the ability to test for prime numbers:
put isPrime("5") -- returns true if the number is a prime number (hopefully!)
I will update the documentation to include these additions in due course. As always, please ensure you fully refresh your browser cache between testing various versions of webtalk (just in case you are seeing errors in the testing pages). Here's a great little firefox extension I use for this.
v163
I added switch case statements today. You can now use:
switch myChoice
case "a"
put "You chose option A."
break
case "b"
put "You chose option B."
break
end switch
switch-case.json
v164
Expanded the replace regex functions, added a matchText function (examples in the test pages), and added a formatNumber function.
put "<p>Hello <b>World</b></p>" into thtml
put replaceRegex("<[^>]*>", "", thtml)
outputs:
Hello World
replace-regex.json
Here's the matchText function being used to pinpoint a number in a string:
put matchtext("[0-9]+", "The price is £25.99", priceDigits)
put priceDigits
returns:
true
25
matchtext.json
Here's an example of formatting a number in a one-liner for currency display:
put formatNumber(1234.567, 2, ",", ".", "£")
returns:
£1,234.57
Also made sure that we support both the long and short forms of the date and time:
put the long date -- Monday, June 9, 2025
put the short date -- 6/9/2025
put the long time -- 6:57:47 PM
put the short time -- 6:57
date-time-long-short.json
Also added the dateFormat function, as a quick way to reference certain parts of the dateitems. You can do this with any valid dateitems string:
put dateFormat("2025,6,9,18,24,30", "%Y-%m-%d %H:%M:%S - %A, %B %e, %Y")
or you can do this with the dateitems function:
put dateFormat(the dateitems, "%Y-%m-%d %H:%M:%S - %A, %B %e, %Y")
dateFormat.json
v165
Added the ability to set a backgroundPattern property:
set the backgroundPattern of image "new" to the imageData of image "image1"
backgroundPattern.json
v166
I was messing about with the answer colour (or color, whichever you prefer). I added the web hex colour to the dialog:
But then I thought, why not make this a function so that people can easily convert between RGB and Web hex values (or back again). So you can now do:
put convert colour 255,118,0 -- would output #FF7600
put convert color 180,0,255 -- using US english spelling, would output #B400FF
put convert colour #73D216 -- would output 115,210,22
answer-colour.json
v167
Something else that I thought might be handy to add. If you reference an object by name that does not exist, yet you have something similar already on the card, the interpreter can now prompt you so you are aware of any naming mismatch (case sensitive errors)
v168
Added support for the 'grab me' function. As in:
on mousedown
grab me
end mousedown
grab-and-intersect-test.json
v169
Since we already have move, rotate, and spin - it seemed a good idea to support flipping:
flip image("theImageToFlip", "imageA", "imageB", 300, left, true)
I should explain the parameters this takes. Parameter 1 is the image you want to perform the effect on. Parameter 2 and 3 (imageA and imageB) are your images we use for the flip, parameter 4 is the speed, and parameter 5 is the direction of flip, and parameter 6 is true or false (depending on if you want to use a perspective effect). The non-perspective effect needs a bit more work though.
flip-cards.json
v170
Fixed a few issues with the move command (for some reason, I'd forgot to allow it to move image objects).
move-image.json
Cleaned up the inspector properties, which fixes the setting of the border property (both for standard objects, and for custom graphics with points)
background-graphic.json
In addition, graphics - even ones with custom points, can now have their backgroundPattern set.
on mousedown
set the backgroundPattern of graphic "myGraphic" to the imageData of image "myImage"
end mousedown
v171
Expanded the intersect function.
intersect-test-2.json
Now, when we use:
on mousedown
put intersect(graphic "dragme",image "intersectTest") into tResult
put tResult
end mousedown
The intersect function can detect transparent areas of PNG images, and these are now counted as 'not-intersecting' (false). That doesn't sound like much, but was actually quite hard to do.
v172
Just backtracked slightly, and fixed a bug with the incorrect borderColor/borderColour getting inherited between different stacks being loaded. Also went back and fixed the flip image so it works properly with non-perspective variants.
flip-2.json
v173
Bug fixing involving multi-line text fields (which was more about stopping interference from various browsers). You won't notice any changes as they are all under the surface. Nothing to report other than setting textColor of lines will now work a lot more reliably:
on mousedown
-- assuming you had a field test, with text in line 1
set the textcolor of line 1 of field "test" to red
wait 1 second
set the textcolor of line 1 of field "test" to green
end mousedown
Added a new command called applyForce. This adds force to an object in a specific direction, with a specific amount:
This is so you don't have to go through coding custom repeat loops, or checking for intersects in x duration (although you could of course still choose to do that).
Added a new object type, scrollbars. (think 'Progressbar')
Implemented the mouseDoubleUp/DoubleDown messages.
The pixelColour (or pixelColor if you prefer), returns the colour of a pixel at a specific x and y point. Even if another window or popup was to overlap that specific x,y point.
Vastly improved the if else condition statement, so that it's a lot more robust, and 'fuzzy'. You can also now use parentheses for if else conditions:
Added a new removeDuplicates function. Also continued work on making fields more reliable (or rather, preventing browser interference).
Modified the spin command with the addition of a "logical" keyword, a few interface tweaks, and improvements to the 'exit repeat' command.
Continued work on field object formatting, added methods to reference a property array of an object, implemented the do command (execute a variable as a line of hypertalk script), added numToCodepoint and codepointToNum. Also, the openstack message is now supported in a card along with the opencard one which was already there. See the test pages for examples.
Just a quick bit of tidy-up, improving fixes for browsers interfering with text field objects. Not much to say, other than multi-line text fields should be a lot more reliable to edit manually - however, this isn't perfect and I'm still refining it. (changes to "field-fix.js")
Added the lastkeys([number]) for getting a list of the last pressed keys.
Text formatting now reapplies to multi-line fields on stack reopen.
Object IDs are now retained upon stack reopen.
Scrollbars no longer revert to 150px wide when you change their thumbPosition property:
Added vScroll position function for when you scroll a field.
Added referencing objects by ID (every combination I could think of).
Added the ability to count the number of controls of this card as well:
I implemented changing a button into a checkbox (the isCheckbox property on the inspector).
(You can do this through the inspector, or you can do this via script):
Buttons now also support highlighted states.
In the screenshot above, we have Firefox 140 on the left and Chromium/Chrome on the right.
I've refined the if, then, else conditional statements. They should be much improved. This now has it's own dedicated file (expressionparser.js) to work out what is actually meant in if statements, and properly parse them.
This is quite a large change, even though it won't visually seem like much has been modified. I've also been working on a few more examples and adding to the live demos.
Implemented "the last object", so it's now possible to reference the last object created.
Create an object, or if you drag an object from the tools palette, you can now run:
I've added the ability to rotate scrollbar objects. It turns out, this is handier than I first thought.
I've also added the export image command, although more will follow on this at a later stage.