Skip to content

Commit 5a4057e

Browse files
committed
docs
1 parent 6a8d3f0 commit 5a4057e

34 files changed

Lines changed: 1187 additions & 53 deletions

.github/workflows/deploy.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Deploy Docs
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: pages
16+
cancel-in-progress: true
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
25+
- name: Setup Bun
26+
uses: oven-sh/setup-bun@v2
27+
with:
28+
bun-version: '1.1.36'
29+
30+
- name: Install dependencies
31+
run: bun install --frozen-lockfile
32+
33+
- name: Determine base path
34+
id: pages
35+
run: |
36+
REPO_NAME="${GITHUB_REPOSITORY#*/}"
37+
if [[ "$REPO_NAME" == *.github.io ]]; then
38+
echo "base_path=" >>"$GITHUB_OUTPUT"
39+
else
40+
echo "base_path=/$REPO_NAME" >>"$GITHUB_OUTPUT"
41+
fi
42+
43+
- name: Build static site
44+
run: bun run docs:build
45+
env:
46+
NEXT_PUBLIC_BASE_PATH: "${{ steps.pages.outputs.base_path }}"
47+
NEXT_TELEMETRY_DISABLED: '1'
48+
49+
- name: Upload artifact
50+
uses: actions/upload-pages-artifact@v3
51+
with:
52+
path: ./out
53+
54+
deploy:
55+
runs-on: ubuntu-latest
56+
needs: build
57+
environment:
58+
name: github-pages
59+
url: ${{ steps.deployment.outputs.page_url }}
60+
steps:
61+
- name: Deploy to GitHub Pages
62+
id: deployment
63+
uses: actions/deploy-pages@v4

.source/index.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
// @ts-nocheck -- skip type checking
2-
import * as docs_1 from "../content/docs/test.mdx?collection=docs&hash=1760316941584"
3-
import * as docs_0 from "../content/docs/index.mdx?collection=docs&hash=1760316941584"
2+
import * as docs_18 from "../content/docs/spec/typing.mdx?collection=docs&hash=1760326440684"
3+
import * as docs_17 from "../content/docs/spec/stdlib.mdx?collection=docs&hash=1760326440684"
4+
import * as docs_16 from "../content/docs/spec/state-machines.mdx?collection=docs&hash=1760326440684"
5+
import * as docs_15 from "../content/docs/spec/security.mdx?collection=docs&hash=1760326440684"
6+
import * as docs_14 from "../content/docs/spec/prompting.mdx?collection=docs&hash=1760326440684"
7+
import * as docs_13 from "../content/docs/spec/productivity.mdx?collection=docs&hash=1760326440684"
8+
import * as docs_12 from "../content/docs/spec/llm-signatures.mdx?collection=docs&hash=1760326440684"
9+
import * as docs_11 from "../content/docs/spec/language.mdx?collection=docs&hash=1760326440684"
10+
import * as docs_10 from "../content/docs/spec/grammar.mdx?collection=docs&hash=1760326440684"
11+
import * as docs_9 from "../content/docs/spec/errors.mdx?collection=docs&hash=1760326440684"
12+
import * as docs_8 from "../content/docs/spec/effects.mdx?collection=docs&hash=1760326440684"
13+
import * as docs_7 from "../content/docs/spec/contracts-proofs.mdx?collection=docs&hash=1760326440684"
14+
import * as docs_6 from "../content/docs/guides/svelte.mdx?collection=docs&hash=1760326440684"
15+
import * as docs_5 from "../content/docs/guides/react.mdx?collection=docs&hash=1760326440684"
16+
import * as docs_4 from "../content/docs/guides/compile-to-typescript.mdx?collection=docs&hash=1760326440684"
17+
import * as docs_3 from "../content/docs/guides/compile-to-rescript.mdx?collection=docs&hash=1760326440684"
18+
import * as docs_2 from "../content/docs/test.mdx?collection=docs&hash=1760326440684"
19+
import * as docs_1 from "../content/docs/index.mdx?collection=docs&hash=1760326440684"
20+
import * as docs_0 from "../content/docs/examples.mdx?collection=docs&hash=1760326440684"
421
import { _runtime } from "fumadocs-mdx/runtime/next"
522
import * as _source from "../source.config"
6-
export const docs = _runtime.docs<typeof _source.docs>([{ info: {"path":"index.mdx","fullPath":"content/docs/index.mdx"}, data: docs_0 }, { info: {"path":"test.mdx","fullPath":"content/docs/test.mdx"}, data: docs_1 }], [])
23+
export const docs = _runtime.docs<typeof _source.docs>([{ info: {"path":"examples.mdx","fullPath":"content/docs/examples.mdx"}, data: docs_0 }, { info: {"path":"index.mdx","fullPath":"content/docs/index.mdx"}, data: docs_1 }, { info: {"path":"test.mdx","fullPath":"content/docs/test.mdx"}, data: docs_2 }, { info: {"path":"guides/compile-to-rescript.mdx","fullPath":"content/docs/guides/compile-to-rescript.mdx"}, data: docs_3 }, { info: {"path":"guides/compile-to-typescript.mdx","fullPath":"content/docs/guides/compile-to-typescript.mdx"}, data: docs_4 }, { info: {"path":"guides/react.mdx","fullPath":"content/docs/guides/react.mdx"}, data: docs_5 }, { info: {"path":"guides/svelte.mdx","fullPath":"content/docs/guides/svelte.mdx"}, data: docs_6 }, { info: {"path":"spec/contracts-proofs.mdx","fullPath":"content/docs/spec/contracts-proofs.mdx"}, data: docs_7 }, { info: {"path":"spec/effects.mdx","fullPath":"content/docs/spec/effects.mdx"}, data: docs_8 }, { info: {"path":"spec/errors.mdx","fullPath":"content/docs/spec/errors.mdx"}, data: docs_9 }, { info: {"path":"spec/grammar.mdx","fullPath":"content/docs/spec/grammar.mdx"}, data: docs_10 }, { info: {"path":"spec/language.mdx","fullPath":"content/docs/spec/language.mdx"}, data: docs_11 }, { info: {"path":"spec/llm-signatures.mdx","fullPath":"content/docs/spec/llm-signatures.mdx"}, data: docs_12 }, { info: {"path":"spec/productivity.mdx","fullPath":"content/docs/spec/productivity.mdx"}, data: docs_13 }, { info: {"path":"spec/prompting.mdx","fullPath":"content/docs/spec/prompting.mdx"}, data: docs_14 }, { info: {"path":"spec/security.mdx","fullPath":"content/docs/spec/security.mdx"}, data: docs_15 }, { info: {"path":"spec/state-machines.mdx","fullPath":"content/docs/spec/state-machines.mdx"}, data: docs_16 }, { info: {"path":"spec/stdlib.mdx","fullPath":"content/docs/spec/stdlib.mdx"}, data: docs_17 }, { info: {"path":"spec/typing.mdx","fullPath":"content/docs/spec/typing.mdx"}, data: docs_18 }], [{"info":{"path":"meta.json","fullPath":"content/docs/meta.json"},"data":{"title":"Docs"}}, {"info":{"path":"guides/meta.json","fullPath":"content/docs/guides/meta.json"},"data":{"title":"Guides"}}, {"info":{"path":"spec/meta.json","fullPath":"content/docs/spec/meta.json"},"data":{"title":"Specification"}}])

.source/source.config.mjs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ import {
55
frontmatterSchema,
66
metaSchema
77
} from "fumadocs-mdx/config";
8+
import fs from "node:fs";
9+
import path from "node:path";
10+
import { bundledLanguages } from "shiki";
11+
var shikiGrammarDir = path.join(process.cwd(), "lib/shiki");
12+
var betterscriptGrammar = JSON.parse(
13+
fs.readFileSync(path.join(shikiGrammarDir, "betterscript.tmLanguage.json"), "utf8")
14+
);
15+
var ebnfGrammar = JSON.parse(
16+
fs.readFileSync(path.join(shikiGrammarDir, "ebnf.tmLanguage.json"), "utf8")
17+
);
818
var docs = defineDocs({
919
docs: {
1020
schema: frontmatterSchema,
@@ -18,7 +28,38 @@ var docs = defineDocs({
1828
});
1929
var source_config_default = defineConfig({
2030
mdxOptions: {
21-
// MDX options
31+
remarkCodeTabOptions: {
32+
parseMdx: true
33+
},
34+
// Enable custom Shiki language for betterscript
35+
rehypeCodeOptions: {
36+
themes: {
37+
light: "github-light",
38+
dark: "github-dark"
39+
},
40+
langs: [
41+
...Object.keys(bundledLanguages),
42+
{
43+
// Minimal TextMate grammar to keep ```ebnf``` fences rendering without errors
44+
...ebnfGrammar
45+
},
46+
{
47+
// Shiki custom language object, loaded from local TextMate grammar
48+
aliases: ["bs"],
49+
name: "betterscript",
50+
scopeName: "source.betterscript",
51+
// Merge the grammar JSON
52+
...betterscriptGrammar
53+
}
54+
],
55+
langAlias: {
56+
bs: "betterscript",
57+
rescript: "purescript",
58+
ReScript: "purescript",
59+
res: "purescript",
60+
text: "ebnf"
61+
}
62+
}
2263
}
2364
});
2465
export {

README.md

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,20 @@
1-
# betterscript-docs
1+
# BetterScript
22

3-
This is a Next.js application generated with
4-
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
3+
LLM-first language with deterministic semantics, compiling to ReScript and TypeScript.
54

6-
Run development server:
5+
## Docs
76

8-
```bash
9-
npm run dev
10-
# or
11-
pnpm dev
12-
# or
13-
yarn dev
14-
```
15-
16-
Open http://localhost:3000 with your browser to see the result.
17-
18-
## Explore
19-
20-
In the project, you can see:
21-
22-
- `lib/source.ts`: Code for content source adapter, [`loader()`](https://fumadocs.dev/docs/headless/source-api) provides the interface to access your content.
23-
- `lib/layout.shared.tsx`: Shared options for layouts, optional but preferred to keep.
24-
25-
| Route | Description |
26-
| ------------------------- | ------------------------------------------------------ |
27-
| `app/(home)` | The route group for your landing page and other pages. |
28-
| `app/docs` | The documentation layout and pages. |
29-
| `app/api/search/route.ts` | The Route Handler for search. |
7+
- Full specification lives under `content/docs` and is served at `/docs`.
8+
- Start at `content/docs/index.mdx`.
309

31-
### Fumadocs MDX
10+
## Develop
3211

33-
A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
34-
35-
Read the [Introduction](https://fumadocs.dev/docs/mdx) for further details.
36-
37-
## Learn More
12+
```bash
13+
bun run docs:dev
14+
```
3815

39-
To learn more about Next.js and Fumadocs, take a look at the following
40-
resources:
16+
## Build
4117

42-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
43-
features and API.
44-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
45-
- [Fumadocs](https://fumadocs.dev) - learn about Fumadocs
18+
```bash
19+
bun run docs:build
20+
```

content/concept.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ Pre-Commit Hooks
3737
Build Speed
3838
Errors with Suggestions
3939
Embeded Open Telemetry
40+

content/docs/examples.mdx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: Examples
3+
description: End-to-end examples demonstrating intents, effects, agents, and contracts.
4+
---
5+
6+
## Chat Summarizer
7+
8+
```betterscript
9+
intent Summarize [text: string] -> [summary: string]
10+
11+
effect LLM { fn complete(prompt: string): Task<string> }
12+
13+
fn summarize(i: Summarize) with LLM: Task<{ summary: string }> {
14+
let prompt = "Summarize: " ++ i.text
15+
let out = await LLM.complete(prompt)
16+
{ summary: out }
17+
}
18+
```
19+
20+
TypeScript:
21+
22+
```ts
23+
type LLM = { complete: (prompt: string) => Promise<string> };
24+
async function summarize(i: { text: string }, LLM: LLM): Promise<{ summary: string }> {
25+
const out = await LLM.complete(`Summarize: ${i.text}`);
26+
return { summary: out };
27+
}
28+
```
29+
30+
## Counter Agent + Machine
31+
32+
```betterscript
33+
agent Counter(0) { state count: int = 0; on inc(n: int): int { count = count + n; count } }
34+
machine CounterUI { /* ... UI events ... */ }
35+
```
36+
37+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: Compile to ReScript
3+
description: Semantic mapping and examples from BetterScript to ReScript.
4+
---
5+
6+
## Types
7+
8+
```betterscript
9+
type Id = Id(string)
10+
type User = { id: Id, name: string }
11+
```
12+
13+
```rescript
14+
type id = Id(string)
15+
type user = { id: id, name: string }
16+
```
17+
18+
## Variants & Match
19+
20+
```betterscript
21+
type Purchase = Granted(User) | Denied(string)
22+
fn access(p: Purchase): bool { match p { Granted(_) -> true | Denied(_) -> false } }
23+
```
24+
25+
```rescript
26+
type purchase = Granted(user) | Denied(string)
27+
let access = (p: purchase): bool => switch p { | Granted(_) => true | Denied(_) => false }
28+
```
29+
30+
## Modules
31+
32+
```betterscript
33+
module Math { export fn add(a: int, b: int): int { a + b } }
34+
```
35+
36+
```rescript
37+
module Math = { let add = (a: int, b: int): int => a + b }
38+
```
39+
40+
## Effects & Tasks
41+
42+
Model effects via module capabilities; tasks via `Js.Promise`.
43+
44+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: Compile to TypeScript
3+
description: Mapping BetterScript constructs to idiomatic TypeScript.
4+
---
5+
6+
## ADTs
7+
8+
```betterscript
9+
type Purchase = Granted(user: User) | Denied(reason: string)
10+
```
11+
12+
```ts
13+
type Purchase =
14+
| { tag: "Granted"; user: User }
15+
| { tag: "Denied"; reason: string };
16+
```
17+
18+
## Pattern Matching
19+
20+
```betterscript
21+
fn describe(p: Purchase): string {
22+
match p { Granted(user: u) -> u.name | Denied(reason: r) -> r }
23+
}
24+
```
25+
26+
```ts
27+
function describe(p: Purchase): string {
28+
switch (p.tag) {
29+
case "Granted": return p.user.name;
30+
case "Denied": return p.reason;
31+
}
32+
}
33+
```
34+
35+
## Async & Parallel
36+
37+
```betterscript
38+
let [a,b] = await parallel (fa(), fb())
39+
```
40+
41+
```ts
42+
const [a, b] = await Promise.all([fa(), fb()]);
43+
```
44+
45+
## Contracts
46+
47+
Runtime checks emitted behind feature flag; Zod optional for external IO.
48+
49+

content/docs/guides/meta.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"title": "Guides",
3+
"order": [
4+
"compile-to-rescript",
5+
"compile-to-typescript",
6+
"react",
7+
"svelte"
8+
]
9+
}
10+

content/docs/guides/react.mdx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
title: React Interop
3+
description: Using BetterScript modules and ADTs from React.
4+
---
5+
6+
## Components
7+
8+
```betterscript
9+
type Model = Loading | Ready(data: string) | Error(msg: string)
10+
11+
module UI {
12+
export fn view(m: Model): ReactNode { /* compiled TSX */ }
13+
}
14+
```
15+
16+
TypeScript component consuming ADT:
17+
18+
```tsx
19+
function View(props: { m: Model }) {
20+
switch (props.m.tag) {
21+
case "Loading": return <Spinner/>;
22+
case "Ready": return <div>{props.m.data}</div>;
23+
case "Error": return <Error msg={props.m.msg}/>;
24+
}
25+
}
26+
```
27+
28+

0 commit comments

Comments
 (0)