Skip to content

Commit 6b4c2f3

Browse files
authored
add new blog post with community tag and bluesky social for author (#978)
* add new blog post with community tag and bluesky social for author * remove console * add back newline * change to the 5th
1 parent 4774d48 commit 6b4c2f3

File tree

4 files changed

+173
-12
lines changed

4 files changed

+173
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
---
2+
author: josh-derocher-vlk
3+
date: "2025-03-05"
4+
title: What can I do with ReScript?
5+
badge: community
6+
description: |
7+
Can I use Vite, or Next.js? Is it only for React? Can I use Node or Deno?
8+
---
9+
10+
You've taken a look and ReScript and you want to try it out, but how do you get started? There's the [installation](/docs/manual/latest/installation) page in the docs,
11+
which is great if you want to set up a new React app using [create-rescript-app](https://github.com/rescript-lang/create-rescript-app). There's instructions on how to add it to an existing project or set it up manually.
12+
But that doesn't really answer the question "Can I use this with X?".
13+
14+
## You can use ReScript anywhere you can use JavaScript
15+
ReScript is just a language that compiles to JavaScript. Unlike other language like [Elm](https://elm-lang.org/) or [PureScript](https://www.purescript.org/) ReScript doesn't have a recommended framework or independent ecosystem, it's just part of the normal JavaScript world.
16+
17+
Here's a really basic example that you can run in Node after compiling:
18+
19+
```res
20+
// index.res
21+
Console.log("Hello")
22+
```
23+
24+
Just run `node index.res.js` and you'll see "Hello" logged to the console. You can import compiled ReScript into any project that could import JavaScript.
25+
If you can use `.js` or `.mjs` files, you can use ReScript. This does mean that languages with different file formats like Vue or Svelte require you to import the compiled JavaScript instead of writing it directly in the `.vue` or `.svelte` files.
26+
27+
Real world projects are more than JavaScript files that you write; they use libraries and frameworks. This is where [bindings](/docs/manual/latest/external) come into play.
28+
A binding is a way to tell ReScript the types and imports from external JavaScript. You can think of bindings in the same way that you need to create a `*.d.ts` file to add types to a JavaScript library that doesn't use TypeScript.
29+
30+
ReScript has great integration with [React](/docs/react/latest/introduction) and those bindings are kept up to date by the core team, but that doesn't mean you don't have other options!
31+
32+
## Using existing bindings
33+
While ReScript isn't as large as TypeScript it has a small but growing list of bindings you can find on NPM. The website has a [package explorer](/packages) you can use to find official and community maintained bindings.
34+
Many major libraries have existing bindings. Here's a small set of what you can find.
35+
36+
-[Node](https://github.com/TheSpyder/rescript-nodejs)
37+
-[Material UI](https://github.com/cca-io/rescript-mui)
38+
-[Bun](https://github.com/zth/rescript-bun)
39+
-[Deno](https://github.com/tsirysndr/rescript-deno)
40+
-[Deno's Fresh](https://github.com/jderochervlk/rescript-fresh)
41+
-[Vitest](https://github.com/cometkim/rescript-vitest)
42+
-[Rxjs](https://github.com/noble-ai/rescript-rxjs)
43+
-[React Helmet](https://github.com/MoOx/rescript-react-helmet)
44+
-[Jotai](https://github.com/Fattafatta/rescript-jotai)
45+
-[Headless UI](https://github.com/cbowling/rescript-headlessui)
46+
47+
48+
## Using libraries and frameworks created for ReScript
49+
Bindings are great if you want to work with libraries written with JavaScript, but there are great options for libraries and frameworks written with ReScript, which means you don't need bindings.
50+
51+
-[ReScript Schema](https://github.com/DZakh/rescript-schema) - The fastest parser in the entire JavaScript ecosystem with a focus on small bundle size and top-notch DX.
52+
-[rescript-relay](https://github.com/zth/rescript-relay) - This is an amazing way to connect React to Relay and GraphQL
53+
-[rescript-rest](https://github.com/DZakh/rescript-rest) - Fully typed RPC-like client, with no need for code generation!
54+
-[rescript-edgedb](https://github.com/zth/rescript-edgedb) - Use EdgeDB fully type safe in ReScript. Embed EdgeQL right in your ReScript source code.
55+
-[ResX](https://github.com/zth/res-x) - A ReScript framework for building server-driven web sites and applications.
56+
57+
## Creating your own bindings
58+
At some point you will probably have to use a library that doesn't have bindings available. Asking on the [forum](https://forum.rescript-lang.org/) is a great place to start. Someone else might have bindings already in a project that they just haven't published to NPM.
59+
You can also get help and guidance on how to write bindings for what you need. Usually you can figure out what you need from looking at a libraries official docs.
60+
You don't need to write bindings for an entire library, or even for all of a functions arguments. Just write what you need as you go.
61+
62+
Let's take a look at the `format` function from [date-fns](https://date-fns.org/). We can see the [arguments in the docs](https://date-fns.org/v4.1.0/docs/format#arguments), and how it should be imported and used.
63+
```ts
64+
// type signature
65+
function format(
66+
date:string|number|Date,
67+
formatStr:string,
68+
options?:FormatOptions
69+
):string
70+
71+
// how it's imported
72+
import { format } from"date-fns";
73+
74+
// how it's used
75+
const result =format(newDate(2014, 1, 11), 'MM/dd/yyyy')
76+
```
77+
78+
That's all we need to know to write bindings to use this function in ReScript.
79+
The first thing we need to figure out is how to handle the type for what `date-fns` considers to be a `date`, which is `Date | string | number`. In ReScript things can't just be of different types like they can in JavaScript or TypeScript. There are a couple options here; you can make a function for each type such as `formatString` and `formatDate`, or you can create a [variant type](/docs/manual/latest/variant) to map to the possible input types.
80+
Creating a function for each type is simpler, and it's most likely how you will use the library in your project. You probably have a standard type for Dates already. We'll also need a type for `FormatDateOptions` in case we want to pass options. We'll use [labeled argmuments](/docs/manual/latest/function#labeled-arguments) for our binding.
81+
```res
82+
// DateFns.res - you might want to put this in a folder called "bindings" or "external"
83+
type formatDateOptions // we're not even going to add anything to this yet until we need something
84+
85+
@module("date-fns") // this is the import path for the module
86+
external formatString: (
87+
~date: string, // the date string
88+
~formatStr: string, // how we want it formatted
89+
~options: formatDateOptions=?, // =? means the argument is optional
90+
) => string = "format" // "format" is the name of the function we are importing from the module
91+
```
92+
93+
Now we can use the function!
94+
<CodeTablabels={["ReScript", "JS Output"]}>
95+
```res
96+
let formattedDate = DateFns.formatString(~date="2021-09-01", ~formatStr="MMMM dd, yyyy")
97+
```
98+
99+
```js
100+
import*asDateFnsfrom"date-fns";
101+
102+
var formattedDate =DateFns.format("2021-09-01", "MMMM dd, yyyy");
103+
```
104+
</CodeTab>
105+
106+
If we need to use `FormatDateOptions` we can add to our type definition as needed. The first option is `firstWeekContainsDate` which can either be `1` or `4`.
107+
Here's how we could write bindings for that.
108+
```res
109+
@unboxed
110+
type firstWeekContainsDate =
111+
| @as(1) One
112+
| @as(4) Four
113+
114+
type formatDateOptions = {firstWeekContainsDate: firstWeekContainsDate}
115+
```
116+
117+
And when we use it it will output either `1` or `4`.
118+
<CodeTablabels={["ReScript", "JS Output"]}>
119+
```res
120+
let formattedDate = formatString(
121+
~date="2021-09-01",
122+
~formatStr="MMMM dd, yyyy",
123+
~options={firstWeekContainsDate: Four},
124+
)
125+
```
126+
127+
```js
128+
import*asDateFnsfrom"date-fns";
129+
130+
var formattedDate =DateFns.format("2021-09-01", "MMMM dd, yyyy", {
131+
firstWeekContainsDate:4
132+
});
133+
```
134+
</CodeTab>
135+
136+
You can write new bindings and extend existing types as you need.
137+
138+
## How can I get started?
139+
You can [follow this guide](/docs/manual/v11.0.0/converting-from-js) to add ReScript to an existing JavaScript project to get a feel for how the language works and interacts with JavaScript.
140+
The forum is also a great place to ask questions! Feel free to drop by and ask how to get started with a specific framework or project that you want to work on,
141+
and you'll probably get great advice and information from users who have already used ReScript for something similar.
142+
143+
Happy coding!

src/Blog.res

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module Badge = {
2424
@react.component
2525
letmake= (~badge: BlogFrontmatter.Badge.t) => {
2626
letbgColor=switchbadge {
27-
| Preview | Roadmap | Release=>"bg-turtle"
27+
| Preview | Roadmap | Release| Community=>"bg-turtle"
2828
| Testing=>"bg-orange"
2929
}
3030

@@ -170,7 +170,10 @@ module FeatureCard = {
170170
<div>
171171
<a
172172
className="hover:text-gray-60"
173-
href={"https://x.com/"++author.xHandle}
173+
href={switchauthor.social {
174+
| X(handle) =>"https://x.com/"++handle
175+
| Bluesky(handle) =>"https://bsky.app/profile/"++handle
176+
}}
174177
rel="noopener noreferrer">
175178
{React.string(author.fullname)}
176179
</a>

src/BlogArticle.res

+4-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ module AuthorBox = {
3939
<divclassName="w-10 h-10 bg-berry-40 block rounded-full mr-3"> authorImg </div>
4040
<divclassName="body-sm">
4141
<a
42-
href={"https://x.com/"++author.xHandle}
42+
href={switchauthor.social {
43+
| X(handle) =>"https://x.com/"++handle
44+
| Bluesky(handle) =>"https://bsky.app/profile/"++handle
45+
}}
4346
className="hover:text-gray-80"
4447
rel="noopener noreferrer">
4548
{React.string(author.fullname)}

src/common/BlogFrontmatter.res

+21-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
typesocial=X(string) | Bluesky(string)
2+
13
typeauthor= {
24
username: string,
35
fullname: string,
46
role: string,
57
imgUrl: string,
6-
xHandle: string,
8+
social: social,
79
}
810

911
letauthors= [
@@ -12,56 +14,63 @@ let authors = [
1214
fullname: "Hongbo Zhang",
1315
role: "Compiler & Build System",
1416
imgUrl: "https://pbs.twimg.com/profile_images/1369548222314598400/E2y46vrB_400x400.jpg",
15-
xHandle: "bobzhang1988",
17+
social: X("bobzhang1988"),
1618
},
1719
{
1820
username: "chenglou",
1921
fullname: "Cheng Lou",
2022
role: "Syntax & Tools",
2123
imgUrl: "https://pbs.twimg.com/profile_images/554199709909131265/Y5qUDaCB_400x400.jpeg",
22-
xHandle: "_chenglou",
24+
social: X("_chenglou"),
2325
},
2426
{
2527
username: "maxim",
2628
fullname: "Maxim Valcke",
2729
role: "Syntax Lead",
2830
imgUrl: "https://pbs.twimg.com/profile_images/970271048812974080/Xrr8Ob6J_400x400.jpg",
29-
xHandle: "_binary_search",
31+
social: X("_binary_search"),
3032
},
3133
{
3234
username: "ryyppy",
3335
fullname: "Patrick Ecker",
3436
role: "Documentation",
3537
imgUrl: "https://pbs.twimg.com/profile_images/1388426717006544897/B_a7D4GF_400x400.jpg",
36-
xHandle: "ryyppy",
38+
social: X("ryyppy"),
3739
},
3840
{
3941
username: "rickyvetter",
4042
fullname: "Ricky Vetter",
4143
role: "ReScript & React",
4244
imgUrl: "https://pbs.twimg.com/profile_images/541111032207273984/DGsZmmfr_400x400.jpeg",
43-
xHandle: "rickyvetter",
45+
social: X("rickyvetter"),
4446
},
4547
{
4648
username: "made_by_betty",
4749
fullname: "Bettina Steinbrecher",
4850
role: "Brand / UI / UX",
4951
imgUrl: "https://pbs.twimg.com/profile_images/1366785342704136195/3IGyRhV1_400x400.jpg",
50-
xHandle: "made_by_betty",
52+
social: X("made_by_betty"),
5153
},
5254
{
5355
username: "rescript-team",
5456
fullname: "ReScript Team",
5557
role: "Core Development",
5658
imgUrl: "https://pbs.twimg.com/profile_images/1358354824660541440/YMKNWE1V_400x400.png",
57-
xHandle: "rescriptlang",
59+
social: X("rescriptlang"),
5860
},
5961
{
6062
username: "rescript-association",
6163
fullname: "ReScript Association",
6264
role: "Foundation",
6365
imgUrl: "https://pbs.twimg.com/profile_images/1045362176117100545/MioTQoTp_400x400.jpg",
64-
xHandle: "ReScriptAssoc",
66+
social: X("ReScriptAssoc"),
67+
},
68+
{
69+
username: "josh-derocher-vlk",
70+
fullname: "Josh Derocher-Vlk",
71+
role: "Community Member",
72+
imgUrl: "https://cdn.bsky.app/img/avatar/plain/did:plc:erifxn5qcos2zrxvogse5y5s/bafkreif6v7lrtz24vi5ekumkiwg7n7js55coekszduwhjegfmdopd7tqmi@webp",
73+
social: Bluesky("vlkpack.com"),
6574
},
6675
]
6776

@@ -71,13 +80,15 @@ module Badge = {
7180
| Testing
7281
| Preview
7382
| Roadmap
83+
| Community
7484

7585
lettoString= (c: t): string=>
7686
switchc {
7787
| Release=>"Release"
7888
| Testing=>"Testing"
7989
| Preview=>"Preview"
8090
| Roadmap=>"Roadmap"
91+
| Community=>"Community"
8192
}
8293
}
8394

@@ -98,6 +109,7 @@ let decodeBadge = (str: string): Badge.t =>
98109
| "testing"=>Testing
99110
| "preview"=>Preview
100111
| "roadmap"=>Roadmap
112+
| "community"=>Community
101113
| str=>raise(Json.Decode.DecodeError(`Unknown category "${str}"`))
102114
}
103115

0 commit comments

Comments
 (0)
close