Skip to content

Commit 15306d0

Browse files
committed
Add SAFE from Scratch guide
1 parent 0baae7e commit 15306d0

File tree

6 files changed

+153
-4
lines changed

6 files changed

+153
-4
lines changed

docs/img/safe-from-scratch-1.png

40 KB
Loading

docs/img/safe-from-scratch-2.png

756 Bytes
Loading

docs/img/safe-from-scratch-3.png

8.54 KB
Loading

docs/recipes/ui/add-tailwind.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,11 @@ If you are are using the minimal template or if you are upgrading from an old ve
4949
@tailwind utilities;
5050
```
5151

52-
1. In the `src/Client` folder find the code in `Index.fs` to show the list of todos and add a Tailwind text colour class(text-red-200)
52+
1. Start using tailwind classes e.g.
5353
```fsharp
5454
for todo in model.Todos do
5555
Html.li [
5656
prop.classes [ "text-red-200" ]
5757
prop.text todo.Description
5858
]
59-
```
60-
61-
You should see some nice red "to-do"s proving that Tailwind is now in your project.
59+
```

docs/safe-from-scratch.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
This article shows the steps required in order to create a SAFE Stack 5-style app from scratch. [This repository](https://github.com/CompositionalIT/safe-from-scratch) should be used as a guide to follow whilst reading this tutorial; each section links to a specific commit from the [history of the repository](https://github.com/CompositionalIT/safe-from-scratch/commits/main/).
2+
3+
## 1. Folders and tools
4+
This first section creates some basic folders and tools that will simply coding going forwards and represents some best practices.
5+
6+
### 1.1 [Create a basic source-controlled repository](https://github.com/CompositionalIT/safe-from-scratch/commit/eef17c091ac66e65c02e15267c6327ccb9e848c1)
7+
* Create a new folder.
8+
* Put the folder under source controlled:
9+
```bash
10+
git init
11+
```
12+
* We recommend also creating a `.gitignore` file to ensure that you do not accidentally commit unnecessary files into your repository. *[This example file](https://github.com/CompositionalIT/safe-from-scratch/blob/main/.gitignore) has been generated through VS Code and fine-tuned with extra files / folders required for SAFE Stack applications.*
13+
14+
### 1.2 [Set up basic tooling support](https://github.com/CompositionalIT/safe-from-scratch/commit/21e62db348f6f58046558053313e93338003b7b6)
15+
* Create standard dotnet tooling support with \`dotnet new tool-manifest`.
16+
* Install the Fantomas tool for F# formatting.
17+
```bash
18+
dotnet tool install fantomas
19+
```
20+
* We also recommend creating an `.editorconfig` file which configures Fantomas as required for optimal F# formatting.
21+
* You should also create a basic [`global.json` file](https://github.com/CompositionalIT/safe-from-scratch/blob/main/global.json) to pin the repository to a specific version of .NET.
22+
```bash
23+
dotnet new global.json
24+
```
25+
26+
## 2. Creating client & server
27+
Now that we have basic core tools installed, we can go about creating a basic F# server and client and get them communicating with one another.
28+
29+
### 2.1 [Create a basic server application](https://github.com/CompositionalIT/safe-from-scratch/commit/90b4fcb6ef948886bb872b3b24d3e5a9d21ecdc0)
30+
* Create a folder e.g. `server`.
31+
* Create a plain F# console application
32+
```bash
33+
dotnet new console -lang F#
34+
```
35+
* Reference the Giraffe NuGet package (if you wish to use Paket, feel free to install that tool at this point).
36+
* Create a basic Giraffe application to e.g. simply return the text "Hello world!" for every request.
37+
* Run the application and confirm that it returns the expected text.
38+
```bash
39+
dotnet run
40+
```
41+
42+
### 2.2 [Create a basic client application](https://github.com/CompositionalIT/safe-from-scratch/commit/0c05a1022357b5dd3b2a43d8f3738dcff161b6b4)
43+
* Create a folder e.g. `client`.
44+
* Create another plain F# console application in it.
45+
* Add the Fable dotnet tool.
46+
* To prove that Fable is installed, you should now be able to transpile the stock "Hello from F#" console app into JavaScript.
47+
```bash
48+
dotnet fable
49+
```
50+
51+
### 2.3 [Create a basic web application](https://github.com/CompositionalIT/safe-from-scratch/commit/ac025b31ab49506a8a6199e80ac0825147e21b95)
52+
Now that we have a running HTTP server and the ability to create JS from F#, we can now install the required browser libraries and tools required to host a full app in the browser.
53+
54+
* Create an `index.html` file that will be used as the launch point for the web application; it will also load the JS that is generated by Fable.
55+
* Install Vite with npm (install NPM and Node if you haven't already!).
56+
```bash
57+
npm install vite
58+
```
59+
> Vite is a multi-purpose tool used to aid development and packaging of JavaScript applications.
60+
* You can now launch the application.
61+
```bash
62+
dotnet fable watch -o output -s --run npx vite`
63+
```
64+
This command tells Fable to compile all F# into the `output` folder and then launches Vite, which acts as a local development web server.
65+
66+
* You should see output in your terminal similar to this:
67+
68+
![](img/safe-from-scratch-1.png)
69+
70+
* Browse to the Local URI displayed e.g. `http://localhost:5173` in your browser and view the console output using the dev console (normally `F12`). You should see the console output from your client's `Program.fs` e.g.
71+
72+
![](img/safe-from-scratch-2.png)
73+
74+
### 2.4 [Set up basic Client / Server communication](https://github.com/CompositionalIT/safe-from-scratch/commit/a14a7c9ca117da3b00da4187c6a68bd1cba0b5a3)
75+
Now that we have running client and server F# applications, let's have them communicate with each other over HTTP. We'll use a basic library for this called SimpleHttp.
76+
77+
* Start by adding a configuration file for Vite, `vite.config.mts` which will tell it to redirect traffic destined for the server (which we assume always starts with `/api/`) to port 5000 (which is the port the server runs on).
78+
> See [here](faq/faq-build.md) for more information about this redirection process.
79+
* Add a simple button to the HTML which we will be using handle the "on click" event to communicate with the server.
80+
* Add the **Fable.SimpleHttp** package to the Client project.
81+
* Change your Client `Program.fs` to handle the on-click event of the button so that when it is clicked, it makes a request to e.g. `/api/data` and puts the response in the console and a browser alert.
82+
* Start **both client and server applications**.
83+
* Confirm that when you click the button in the browser, you get the response "Hello world" (sent from the server).
84+
![](img/safe-from-scratch-3.png)
85+
86+
Congratulations! At this stage, you have a working F# client / server application that can communicate over HTTP.
87+
88+
## 3. Adding React
89+
We now spend the next few steps getting React working within the app and with F# support.
90+
91+
### 3.1 [Add basic React support](https://github.com/CompositionalIT/safe-from-scratch/commit/0b331ad76fdc59442bf8024d4300ae1073a20715)
92+
Now that we have a (very) basic F# client/server app, we'll now add support for React - a front-end framework that will enable us to create responsive and rich UIs.
93+
94+
* Add the `react` and `react-dom` packages to your NPM dependencies.
95+
* Add the `@vitejs/plugin-react` and `remotedev` packages to your NPM dev dependencies.
96+
* Add react to the list of plugins in your vite config.
97+
98+
### 3.2 [Add F# React support](https://github.com/CompositionalIT/safe-from-scratch/commit/1409820300e2b09db11003c077ff3e2c82f6d9d2)
99+
Now that we have React added to our application, we can add the appropriate F# libraries such as Feliz to start to use React in a typesafe, F#-friendly manner.
100+
101+
* Add the Feliz NuGet package to the Client project.
102+
* Remove the `<button>` element from the `index.html` - we'll be creating it dynamically with React from now on.
103+
* Add an empty `<div>` with an named `id` to the body of the `index.html`. This will be the "root" element that React will attach to from which to make HTML elements.
104+
* Using the Feliz React wrapper types, replace the contents of your `Program.fs` in the Client project so that it creates a React button that can behave as the original static HTML button.
105+
106+
### 3.3 [Add JSX support *(optional)*](https://github.com/CompositionalIT/safe-from-scratch/commit/78e4093502ec4b8281ec5c14f113e3ad14b4a6f6)
107+
This next step adds Feliz's JSX support, which allows you to embed standard React JSX code directly in your F# applications.
108+
109+
* Add the Fable.Core and Feliz.Jsx.React NuGet packages to the Client project.
110+
* Instead of using the Feliz F# dialect for React components (such as the `button []` element), use standard JSX code with string interpolation.
111+
* Reference `Program.jsx` instead of `Program.js` in your `index.html` file.
112+
* Run the client application using the extra flag that instructs Fable to emit `.jsx` instead of `.js` files:
113+
114+
```bash
115+
dotnet fable watch -o output -s -e .jsx --run npx vite
116+
```
117+
118+
## 4. Taking advantage of F\#
119+
This next section takes advantage of F#'s typing for both client and server.
120+
121+
### 4.1 [Add type-safe Client / Server communication](https://github.com/CompositionalIT/safe-from-scratch/commit/0e47e2fd3d56c6213474dc1af485fa8077375b3a)
122+
* **On the Server**:
123+
* Add the **Fable.Remoting.Giraffe** package.
124+
* Create a new folder, `shared`, and a `Contracts.fs` file inside it.
125+
* Reference this file from both Client and Server projects.
126+
* Inside this file create an API type and a Route builder to be used by Fable Remoting (so that client and server can route traffic).
127+
* On the Server, create an implementation of the Api you just defined, convert it to an Http Handler and replace the `text "Hello world"` call with it.
128+
* **On the Client**:
129+
* Add the **Fable.Remoting.Client** package.
130+
* Instead of using SimpleHttp to make client / server calls, create a Fable Remoting API proxy and use that.
131+
132+
### 4.2 [Add Elmish support](https://github.com/CompositionalIT/safe-from-scratch/commit/1e39a36133ee26c18ddb4f08c11858b33cbaeea1)
133+
Elmish is an F# library modelled closely on the Elm language model for writing browser-based applications, which has popularised the "model-view-update" paradigm.
134+
135+
* Add the **Fable.Elmish.Debugger**, **Fable.Elmish.HMR** and **Fable.Elmish.React** packages.
136+
* Create a set of standard model, view and update types functions.
137+
* Update your basic application root to use Elmish instead of a "raw" ReactDOM root.
138+
* Ensure you add the required polyfill for remotedev in `index.html`.
139+
140+
## 5. More UI capabilities
141+
This last section adds more UX capabilities.
142+
143+
### 5.1 [Add Tailwind support](https://github.com/CompositionalIT/safe-from-scratch/commit/fb8b8d02ac4b9b8e97292af23bf37bcee917daff)
144+
Follow the [Tailwind](ui/add-tailwind.md) guide to add Tailwind to your project.
145+
### 5.2 [Revert to "standard" F# Feliz](https://github.com/CompositionalIT/safe-from-scratch/commit/ce4705c5d497cbebf91ea2e4f74dbd0345901e28) *(optional)*
146+
If you do not want to use the JSX support:
147+
148+
* Remove references to Feliz.JSX
149+
* Do not use `JSX.jsx` to create components but rather standard `[ReactComponent]`.
150+
* Use the standard Feliz types for creating standard React elements such as `div` and `button` etc.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ nav:
110110
- Learning Resources:
111111
- SAFE-Compatible UI Components: "awesome-safe-components.md"
112112
- Learning: "learning.md"
113+
- Creating a SAFE Stack App from Scratch: "safe-from-scratch.md"
113114
- News: "news.md"
114115
- Events: "events.md"
115116
- Support: "support.md"

0 commit comments

Comments
 (0)