Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions apps/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<title>HyperLab — an open-source, AI-native successor to HyperCard</title>
<meta
name="description"
content="Cards, buttons, fields and HyperTalk, with language models built into the language. Runs in the browser."
content="An open-source, AI-native successor to HyperCard. Scripts can ask a language model, and the whole thing runs in your browser."
/>
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<link rel="stylesheet" href="/src/landing.css" />
Expand Down Expand Up @@ -36,8 +36,9 @@ <h1 class="window__title" id="welcome-title">Welcome to HyperLab</h1>
</div>
<div class="window__body">
<p class="hero__line">
An open-source, <strong>AI-native successor to HyperCard</strong>. Cards,
buttons, fields and HyperTalk, and a stack stays editable while it runs.
An open-source, <strong>AI-native successor to HyperCard</strong>. A script
can stop and ask a language model, and the stack stays editable the whole time
it runs.
</p>
<pre class="hero__script" aria-label="A HyperTalk example">
on mouseUp
Expand Down Expand Up @@ -114,57 +115,64 @@ <h2 class="window__title" id="examples-title">Examples</h2>
</div>
<div class="window__body">
<p>
Each opens in the playground, running. Switch to the edit tool to read the
scripts that make it work.
Open any of these and it starts running in the playground. Switch to the edit
tool to read the scripts behind it.
</p>
<ul class="stacks">
<li>
<a class="stack" href="play.html?stack=Cluedo">
<span class="stack__name">Cluedo</span>
<span class="stack__blurb"
>A drawn mansion with clickable rooms, and a case you close by
deduction.</span
>The board is drawn artwork and every room on it is a button, so you
close the case by clicking your way around the mansion.</span
>
</a>
</li>
<li>
<a class="stack" href="play.html?stack=Myst">
<span class="stack__name">Myst</span>
<span class="stack__blurb"
>An island, four Ages, and one book you should not open. Go ▸ Map finds
the trap without running a line.</span
>Wander the island and the Ages it leads to, and try not to open the
wrong book. Go ▸ Map finds that trap by reading the scripts, without
running any of them.</span
>
</a>
</li>
<li>
<a class="stack" href="play.html?stack=LLMs%20for%20n00bs">
<span class="stack__name">LLMs for n00bs</span>
<span class="stack__blurb"
>Nine slides on how a language model works. The last one asks a real
model, and says so plainly when none is set up.</span
>Explains how a language model works, one drawn slide at a time, then
finishes by asking a real one — and says so plainly when you have not
set one up.</span
>
</a>
</li>
<li>
<a class="stack" href="play.html?stack=Address%20Book">
<span class="stack__name">Address Book</span>
<span class="stack__blurb"
>A card per person, one shared background.</span
>Shows what backgrounds are for: everyone gets their own card, while the
layout they all sit on is edited once.</span
>
</a>
</li>
<li>
<a class="stack" href="play.html?stack=Recipe%20Box">
<span class="stack__name">Recipe Box</span>
<span class="stack__blurb"
>Chunk expressions doing arithmetic on the ingredients.</span
>Doubles a recipe by pulling the number out of each ingredient line,
which is what chunk expressions are for.</span
>
</a>
</li>
<li>
<a class="stack" href="play.html?stack=Todo">
<span class="stack__name">Todo</span>
<span class="stack__blurb">A list, a dialog, and a loop.</span>
<span class="stack__blurb"
>Adds whatever you type to the list, then walks back through it to count
what is still outstanding.</span
>
</a>
</li>
</ul>
Expand Down Expand Up @@ -210,9 +218,9 @@ <h2 class="window__title" id="home-title">The desktop application</h2>
same file.
</p>
<p>
Stacks export as a PDF, as a PNG of the map, as a self-contained web page, and
as a <a href="https://beyondloom.com/decker/">Decker</a> deck — from the
playground as readily as from the application.
Every export the application offers works in the playground too: PDF, a PNG of
the map, a self-contained web page, and a
<a href="https://beyondloom.com/decker/">Decker</a> deck.
</p>
</div>
</section>
Expand Down
42 changes: 42 additions & 0 deletions apps/web/src/landing.css
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,45 @@ body {
.colophon a {
color: var(--ink);
}

/* ----------------------------------------------------------------- phones */

/*
* A phone is narrower than `put ai("Summarize this card") into field
* "Summary"`. Scrolling the sample sideways is no help when nothing on
* screen says it scrolls — the line just stops at the edge and looks
* broken — and shrinking it to fit would take it under ten pixels. So on a
* narrow screen it wraps instead.
*/
@media (max-width: 34rem) {
.desk {
padding: 20px 10px 32px;
gap: 20px;
}

.window__body {
padding: 12px 14px;
}

.hero__script {
white-space: pre-wrap;
overflow-wrap: break-word;
font-size: 11px;
}

.hero__line {
font-size: 15px;
}

/* Thumb-sized, and each on its own line rather than three cramped side
by side. */
.hero__buttons {
flex-direction: column;
align-items: stretch;
}

.button {
text-align: center;
padding: 8px 18px;
}
}
14 changes: 7 additions & 7 deletions docs/website.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ follows from there being no server.

## The playground is the application

The playground page renders the desktop's own React components — the card,
the inspector, the assistant sidebar, the map, the dialogs. It can, because
The playground page renders the desktop's own React components, down to the
dialog a script blocks on. It can, because
the desktop keeps its whole shell behind one module (`apps/desktop/src/api.ts`,
a typed wrapper per command), and the renderer never learns which shell
answers. Vite swaps that one module for `apps/web/src/api.ts`; nothing else
in the desktop tree is touched, so the two interfaces cannot drift apart —
they are the same files.

Behind the web `api.ts` sits `crates/web` (`hyperlab-web`): the same crates
the desktop wraps — runtime, parser, persistence, graph, the assistant —
compiled to WebAssembly, exporting one function per desktop command. Its
Behind the web `api.ts` sits `crates/web` (`hyperlab-web`), which wraps the
same crates the Tauri shell wraps, compiled to WebAssembly and exporting one
function per desktop command. Its
`view.rs` is a hand-kept twin of the desktop's, and a test serializes a
snapshot and checks the field names against what the renderer expects.

Expand Down Expand Up @@ -110,8 +110,8 @@ keeps the same shape with the parts a page has:
script blocked mid-line on `ai("…")`. The wire protocol is the same Rust
code the desktop uses (`hyperlab-ai-providers` built without its native
clients); only the transport is the browser's.
- The site being static files is the guarantee's other half: there is no
HyperLab server for a key, a stack, or a question to visit.
- The site being static files is the guarantee's other half: nothing a
browser sends has anywhere of ours to stop off at on the way.

Anthropic requires the `anthropic-dangerous-direct-browser-access` header
before answering a browser at all. Sending it is honest here: the request
Expand Down
Loading