Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Loic Blanchard Portfolio and Blog

License

NotificationsYou must be signed in to change notification settings

skydread1/portfolio

Repository files navigation

Loic logo
Clojure VersionCINetlify StatusContributions welcome

🔷 Portfolio SPA in ClojureScript 🔷

🔷 Rational

This portfolio was implemented withClojureScript. It is a Single Page Application that leveragesreagent, a minimalistic interface between ClojureScript andReact.

For frontend management,re-frame is used. To compile the cljs code and perform hot reloading, I usedfigwheel-main.

The routing is done withreitit.

The markdown content is converted intohiccup (a clojure-friendly markup) and the post/vignette configurations are made in EDN which is validated at compile time with amalli schema.

At compile time, a RSS feed is generated for the clojure blog posts usingclj-rss.

The app is deployed onNetlify every time a branch is merged to master.

🔷 Features

All the posts/vignettes are written in markdown files incontent folder.

The UI supports light/dark mode and is responsive.

At the top of each markdown file, you can provide an EDN config map to add additional properties to the post such as an illustrative image, the order on the page, the title in the URL, github and article links etc...When you create a pull request (PR) to master,Netlify provides a preview of what the new app version would look like.

For development, starting a clj/cljs REPL withfighweel allows you to have the local changes reflected on port 9500 on file save.

🔷 Content

Organization

Each post has its own markdown file in the folder of the page it belongs to.

For instance:

.├── about│   └── aboutme.md└── portfolio    ├── blog-django.md    ├── flybot-website.md    └── props-recommender.md├── blog│   └── just-tick-lib.md

Config Clojure map

A markdown file for a post is divided into three parts, separated by +++ demarcations:

some config map+++post summary+++full post content

Following is an example of clojure map for a post config:

#:post{:date ["2024-02-01""2024-04-01"]:page:portfolio:title"My New Project":css-class"my-project":image-beside #:image{:src"/assets/some-illustrative-img.png":src-dark"/assets/some-illustrative-img-dark.png":alt"A logo"}}

This map goes at the top of a markdown file like so:

post map here+++My project consists in...+++##RationalThe goal of my project is...##StackTo achieve this......

I refer to the post summary part as thevignette because it can conveniently be used on a home page for instance to just display a recap of the projects.

Config validation

To know what params can be provided to the config map, you can have a look at the malli schema invalidation. You can take inspiration from my own posts incontent.

🔷 Compile

At CLJ compile time, the following steps happen:

  1. Read all markdown files
  2. Validate the post configs against aMalli schema
  3. Assoc the post markdown content to the configs
  4. A macro stores a vector of the posts to be loaded in the re-frame DB

At CLJS compile time, the following steps happen:

  1. A re-frame event initializes the re-frame DB, loading all the posts from the clojure macro and the theme from local storage.
  2. Thereitit route table is created
  3. The post markdown are converted to hiccup viamarkdown-to-hiccup.

🔷 Getting Started

Clone the repo

Feel free to clone or fork the repository and modify both the code and post content to suit your need.

Dev

You can perform ClojureScript jack-in to open the webpage in a browser on port9500, alongside an interactive REPL in your IDE.

You can then edit and save source files to trigger hot reloading in the browser.

Prerequisites

  • Delete anymain.js in the resources folder
  • Check ifcljs-out/dev-main.js is the script source inindex.html: that is where figwheel will recompile the cljs when you save a file.

VS Code

If you use VS Code, the jack-in is done in 2 steps to be able to start the REPL in VS Code instead of terminal:

  1. Choose the aliases for the deps and press enter
  2. Choose the ClojureScript REPL you want to launch and press enter

For 2. since our app is only a frontend app, we don't need to load some clj backend deps.

Jack-indeps+figwheel:

  • Deps: no alias to add so just press enter
  • REPL: tick:web/dev and press enter

This should start a cljs REPL in VS Code and open your browser localhost in port 9500.

Emacs

If you use Emacs (or Doom Emacs, or Spacemacs) with CIDER, the CIDER jack-in is done in 3 steps:

  1. C-u M-x cider-jack-in-clj&cljs orC-u M-x cider-jack-in-cljs
  2. By default, emacs use thecider/nrepl alias such as in-M:cider/nrepl. You need to keep this alias at the end such as-M:web/dev:cider/nrepl
  3. Select ClojureScript REPL type:figwheel-main
  4. Select figwheel-main build:dev

Hot reloading

Once the REPL started, saving a cljs file will automatically update the js in your localhost.

However, if you change the content of a markdown file, you will need to save the filemd.clj which is where the macro that read all the markdown files resides. Refresh your browser and the new markdown content will appear.

Prod

Js bundle

The GitHub action is triggered when code is pushed.

I useclojure/tools.build to create tasks related to the build.

It runs thejs-bundle task in the build.clj file as follows:

clojure -T:build js-bundle

This command compiles the cljs to the optimized js bundle that Netlify will use to generate the preview in the PR.

Note: be sure to not forget to usemain.js as script source inindex.html: that is where figwheel will produce the optimize js from your cljs file when you push your update to your online repo.

RSS feed

A RSS feed of the Clojure blog posts is also generated when code is pushed:

clojure -T:build rss-feed

The RSSclojure feed is accessible at the urlblog/rss/clojure-feed.xml

🔷 Tests

Clj tests

The clj macro that loads the markdown files is tested and the test can be run like so:

clj -M:server/test

This test ensure that all your markdown files respect the malli schema.

Cljs tests

The cljs state management tests can be run like so:

clj -M:web/test

These frontend cljs tests ensure that the state (in our re-frame DB) is as expected after user actions (navigation, theme, post interaction etc).

Regression tests on save

The tests mentioned above are also run on every save and the results are displayed athttp://localhost:9500/figwheel-extra-main/auto-testing

Cljs tests (headless) - for CI

In the CI, there is no browser, so we need a specific alias to run the test in headless mode:

clj -M::web/test-headless

🔷 Continuous Integration

Every time you push some code, the following happens:

  • run the clj tests
  • run the cljs tests in headless mode
  • compile the cljs file into the js bundlemain.js and commit it to the repo.

🔷 Continuous Deployment

Opening a pull request (PR) to merge your changes to master, makesNetlify create a preview for you to see how the new version of the website would look like.

Merging to master automatically publishes the last version of the website via Netlify.

Note: The markdown files are converted to hiccup via Clojure macros, so they are converted at compile time.

🔷 Hosting with Netlify

I useNetlify for hosting platform because it is easy to setup and the previews of the new website version on GitHub MR is convenient.

Connecting your repo to Netlify is straight forward and the only configuration we need to update is thePublish directory. It should be set toresources/public because that is where our static files reside.

Note that the server will be hosted in the US by default, and you cannot change the location with the free version.

🔷 Contributing

Feel free to open new issues if you discover bugs or wish to add new features.

🔷 License

Copyright © 2023 Loic Blanchard

Distributed under the MIT License - see theLICENSE file for details.


[8]ページ先頭

©2009-2025 Movatter.jp