... except github.
I didn't mention in the title the language we're going to use, because at this point I'm gonna use the right tool. The right tool being .NET, more specifically, F#.
.NET SDK is required.
So this is a short step-by-step guide.
1. Create a repository on github.com
This one is easy. I'm gonna create a repo with some list of repos.
2. Clone it locally
I'm gonna open my favorite terminal and type
git clone https://github.com/WhiteBlackGoose/MyFunRepos
cd MyFunRepos
3. Initialize the project
dotnet new console -n WebsiteGenerator -lang F#
cd WebsiteGenerator
dotnet add package Giraffe.ViewEngine --prerelease
This creates you an project in F#! Also adds a package that allows to create html tags right in code. Soon about it.
4. Open the project
We're creating something very simple, so you can either open Program.fs
with your favorite text editor, or just open the fsproj
file with an IDE.
5. Create your first webpage
Let's create an empty html page which just has a header and some random text.
open Giraffe.ViewEngine
html [] [
body [] [
h1 [] [ Text "Hello, world" ]
p [] [
Text "Some text"
]
]
]
|> RenderView.AsString.htmlNode
|> fun code -> System.IO.File.WriteAllText("./index.html", code)
Quite readable, right? Let's run it!
dotnet run
firefox index.html
If you don't have firefox, you can try
xdg-open index.html # linux
start index.html # windows
or just open the html page from your file explorer!
6. Add some data to it
You could've made that page with just html. Why do you need F# for it?
Okay, let's complicate the story. This time we're gonna add a list of data and some condition.
open Giraffe.ViewEngine
type Repo = {
name : string
lang : string
}
let myFunReposList = [
{ name = "MyFunRepos"; lang = "F#" }
{ name = "FStarHelloWorld"; lang = "F*" }
{ name = "LambdaCalculusFSharp"; lang = "F#" }
{ name = "AsmToDelegate"; lang = "C#" }
]
html [] [
body [] [
h1 [] [ Text "My Fun Repos" ]
ul [] [
for { name = name; lang = lang } in myFunReposList do
li [] [
p [] [ Text $"Repo {name}" ]
a [_href $"https://github.com/WhiteBlackGoose/{name}"] [ Text name ]
p [] [
Text "Made in "
if lang = "F#" || lang = "C#" then
Text $".NET {lang}"
else
Text lang
]
]
]
]
]
|> RenderView.AsString.htmlNode
|> fun code -> System.IO.File.WriteAllText("./index.html", code)
Okay, what are we doing here? We created a record Repo
, which has two fields (for simplicity). Then I'm creating a list of my repos willing those fields.
There's no string concatenation and no hell with parentheses. We don't even have commas in the end of each line.
Now the most interesting part. See, I'm inserting a regular for
loop right in the ul
element! I'm not creating it in a separate variable or function or anything, I just write it inside the hmtl tag. As if it's some template engine, but it's not, it's a regular language.
I even inserted an if
condition there, which also reads very well!
Let's see what we got for this:
This created a simple html page. That's it. No template engine. This code is written in one programming language, and you can debug it. You're in full control!
7. Automatic website creation
Ok, we made an html page. But it's not a website yet. What we want is that our website could be automatically published on every push. So let's write our Github Actions workflow.
name: Website publish
on:
push:
branches:
- main
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET 6
uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.0.x'
- name: Run generator
run: |
mkdir generated && cd generated
dotnet run --project ../WebsiteGenerator/WebsiteGenerator.fsproj
- name: Push to gh-pages
uses: JamesIves/github-pages-deploy-action@4.1.4
with:
branch: gh-pages
folder: ./generated
The file is quite readable on its own. We install .NET SDK, then we run our generator from a certain folder, and then we just push the folder to the gh-pages
branch! That is it.
8. Activate Pages
- Go to your repo's settings
- Go to Pages
- Choose gh-pages as source branch
- Press Save
9. Enjoy the result!
My url looks like this: whiteblackgoose.github.io/MyFunRepos/.
Now I can easily add content to the page, or create many pages, as well as add some data, maybe even downloading some dataset and then displaying it.
Summary
We created a simple static website in F#! Here's main features of this setup:
- You have full control of it. No static website generator were used
- Syntax of F# is really handy here. You can insert loops, conditionals, and some other control flow constructions right in the page!
- Free hosting and free default domain (but you can set your own domain if you want)
- It takes 5-30 minutes to set up
Top comments (0)