https://github.com/nicholaswmin/nix
one file markdown publisher
https://github.com/nicholaswmin/nix
framework jekyll minimal
Last synced: about 1 year ago
JSON representation
one file markdown publisher
- Host: GitHub
- URL: https://github.com/nicholaswmin/nix
- Owner: nicholaswmin
- Created: 2024-10-21T01:45:41.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-02-08T00:42:17.000Z (about 1 year ago)
- Last Synced: 2025-03-29T02:47:05.647Z (about 1 year ago)
- Topics: framework, jekyll, minimal
- Language: Ruby
- Homepage: https://nicholaswmin.github.io/nix/
- Size: 552 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
> is a single-file static-site generator in 150 lines of [ruby][ruby]
> although nix is fully-working framework, it was written as a proof-of-concept
>
> It's distinguishing characteristic is that it's archicture & system design philosophy
> (over)emphasizes [simplicity][kiss] to an unsual degree;
> even more that [program correctness][corr]
>
> Read more:
> - [The New Jersey style/Worse is Better][njs] by Richard Gabrielle, MIT
> - [Locality of Behaviour][lob]: Carson Gross
>
> It aims to balance 3 competing requirements:
>
> - it must be extemely easy to make sense of
> - it must actually allow publishing a site
> - it must be extremely easy to setup
> - it must be extemely easy to make sense of
> - it must follow conventions to a certain degree
>
> ## todo
> - [ ] tests
> - [ ] cleanup
> - [ ] docs
Instead of installing `X`/`Y` publishing framework on your system,
it inverts the process by embedding the "framework" in the site itself.
- create a repo & drop `nix.rb` into it
- run `nix.rb --init`
- add posts & pages as [markdown][gfm]
- `git push`
... which publishes automatically on [Github Pages][gh-pages].
### todo
- [ ] unit tests
- [ ] data should be pruned outside of this readme
- [ ] code docs
anyone with repository access can edit/publish the site by simply cloning the repo,
add/edit posts and re-pushing to `main`.
```bash
Usage: nix [options]
nix --init create sample blog
nix --build build static HTML
nix --watch rebuild on file change
```
## todo
- [ ] docs
- [ ] unit tests
## Publish a site
1. create a Github repo with enabled pages.
2. drop the [nix.rb](#get-nix) file in it.
3. Run `ruby nix.rb --init` to generate a sample site
5. push to `main` branch
... which publishes a barebones site consistent with the [1kb philosophy](https://1kb.club/) at: `.github.io/`
### Publish new content
1. write markdown in `posts/` and `pages/`
2. push to `main` branch
## quick start
Say you have a repo with the following structure:
`repo`
┣━`nix.rb`
┗━`README.md`
> generate a minimal sample blog:
```bash
ruby nix.rb --init
```
## write posts
- add [markdown][gfm] posts in `/posts`
- add [markdown][gfm] pages in `/pages`
- add images, videos, CSS in `/public`
posts include [syntax highlighting][rouge],
just wrap them in code fences (\`\`\`) as usual:
```js
const hello = 'world'
```
moving on..
> build to static HTML, at `/build`
```bash
ruby nix.rb --build
# build ok!
```
or even better:
> rebuild automatically on file change
```bash
ruby nix.rb --watch
```
## publish it
Just push to `main`.
An autogenerated Github workflow will run `nix --build` to compile
everything once-more & deploy at: https://username.github.io/repo-name.
> `/build` directory is recompiled on `push` so you can safely `.gitignore`
> it entirely.
## post format
just make sure each page or post has:
- an `h1` title on the 1st line
- an `empty line` on the 2nd line
- a `` on the 3rd, ie. `2024-10-18`
the rest is up to you.
> example:
```markdown
# Some pretentious post title
2024-12-20
> A sentence should contain no unnecessary words, a paragraph no unnecessary
> sentences, for the same reason that a drawing should have no unnecessary lines
> and a machine no unnecessary parts. This requires not that the writer make all
> his sentences short, or that he avoid all detail and treat his subjects only
> in outline, but that every word tell
The Elements of Style by William Strunk Jr (1918) ...
```
### get nix
`nix` is just a single-file; it's max 150 lines of code & it includes everything
necessary to develop and publish a [ridicously minimal][club] yet functional
blog site.
grab it from this repo [directly][download], or just `curl` it:
```bash
curl -O https://raw.githubusercontent.com/nicholaswmin/nix/main/nix.rb
```
apart from [Ruby 3.3][ruby] there's nothing to install;
nor any commands to run. You don't need to run `gem install`.
It's not available as a `gem` either;
This is [intentional](#wheres-the-rest-of-it)
## Quirks
### Asset paths
Don't use absolute paths to reference assets.
Github Pages has a well-known quirk of serving from a non-root path,
applicable to all static-site generators.
this won't work:
```html
```
use relative paths instead:
```html
```
even better, use `{{root_url)}`:
```html

```
it's rewritten automatically & resolves to the correct root regardless of the
page position, so it's less error-prone than manually writing relative paths.
> same in markdown:
```md
[1]: {{root_url}}felix.svg
```
### root resolution in ruby
> in case you're extending `nix`:
`root_url` is also available as a method
which has the same effect:
```ruby
root_url('felix.svg')
# ../../felix.svg
```
more context:
```ruby
class CustomPage < HTMLPage
# omitted ...
def render(ctx)
super +
""
end
end
```
## Wheres the rest of it?
> This project is actually part of a weekly workshop I was invited to do
> in an SME. It's an actual project that you can use but it's primary purpose
> was illustrative.
The idea behind it closely mimics [wruby](https://wruby.passthejoe.net/about/),
a static-site generator that generates [sites that are under 1kb][club].
While the whole thing looks more like a code-golfing joke than anything
substantial, it's philosophy is based around serious ideas that emerged
in MIT and Berkley around the 80s(?), regarding software architecture design.
Despite their similarities, under the hood `wruby` is written entirely
procedurally.
There is a clear *lack* of architecture and you can more or less describe it
as a cooking recipe.
What I've done is take wruby and rewrite it's core ideas in
an [Object-Oriented paradigm][oop]; in an effort to make the code more
"modern" and "extensible"; in effect I've proved the entire point of the
argument, the tendency to introduce unnecessary complexity on our own.
`nix` is using a lot of ideas supposedly considered "Best Practices".
Data is moved around in a functional manner; the API is implemented in a fluent
prose with clear hierarchical organisation into classes/types.
Additionally, there's a clear and intentional Separation of Concerns between
persistence code and logic code; the purpose of this is to make it amerable to
unit-testing.
`wruby` has **absolutely none** of the above.
it's really just a bunch of functions glued together.
It's not possible to extend it without pulling out your hair *but* nor is
there any indication that it's purpose was to be extensible.
wruby is actually one of the few projects that I sat through
reading it's entire source-code without getting bored or distracted,
because it is just *that* simple.
Both projects are written in Ruby.
Both projects are based on material from the following essays:
- [Worse is Better][worse-is-better], [Richard P. Gabriel][rpg]
- [Is Worse Really Better?][worse-better], Richard P. Gabriel
- [Locality of Behavior][loc], Carson Gross
- [Chesterson's Fence: A lesson in thinking][chest-fence]
From the Unix-Haters handbook
[Simson Garfinkel](https://en.wikipedia.org/wiki/Simson_Garfinkel)
> [...] Literature that Unix succeeded because of its technical superiority.
> This is not true. Unix was evolutionarily superior to its competitors,
> but not technically superior. Unix became a commercial success because
> it was a virus.
> Its sole evolutionary advantage was its small size, simple design, and
> resulting portability.
> ### From [Worse is Better vs The Right Thing][worse-is-better]
>
> The New Jersey style of software architecture design
> vs the MIT/Stanford approach
>
> [Richard P. Gabriel][rpg], 1991
>
> [... ] I and just about every designer of Common Lisp and CLOS has
> had extreme exposure to the MIT/Stanford style of design.
> The essence of this style can be captured by the phrase *The Right Thing*.
> To such a designer it is important to get all of the following characteristics
> right:
>
> #### Simplicity
> the design must be simple, both in implementation and interface.
> It is more important for the interface to be simple than the implementation.
>
> #### Correctness
> The design must be correct in all observable aspects. Incorrectness is simply
> not allowed.
>
> #### Consistency
> The design must not be inconsistent.
> A design is allowed to be slightly less simple and less complete to avoid
> inconsistency. Consistency is as important as correctness.
>
> #### Completeness
> The design must cover as many important situations as is
> practical. All reasonably expected cases must be covered.
> Simplicity is not allowed to overly reduce completeness.
>
----
>
> [...] The **Worse is Better** philosophy is only slightly different:
>
> #### Simplicity
> The design must be simple, both in implementation and interface.
> It is more important for the implementation to be simple than the interface.
> Simplicity is the most important consideration in a design.
>
> #### Correctness
> The design must be correct in all observable aspects.
> It is slightly better to be simple than correct.
>
> #### Consistency
> The design must not be overly inconsistent.
> Consistency can be sacrificed for simplicity in some cases,
> but it is better to drop those parts of the design that deal with
> less common circumstances than to introduce either implementational
> complexity or inconsistency.nt as correctness.
>
> #### Completeness
> Completeness -- the design must cover as many important situations as is
> practical. All reasonably expected cases should be covered. Completeness
> can be sacrificed in favor of any other quality. In fact, compzleteness must
> be sacrificed whenever implementation simplicity is jeopardized.
> Consistency can be sacrificed to achieve completeness if simplicity is
> retained; especially worthless is consistency of interface.
>
> I have intentionally caricatured the worse-is-better philosophy to convince
> you that it is obviously a bad philosophy and that the New Jersey approach
> is a bad approach.
>
> [...] However, I believe that worse-is-better, even in its strawman form, has
> better survival characteristics than the-right-thing, and that
> the New Jersey approach when used for software is a better approach
> than the MIT approach[...]
[nix]: https://github/com/nicholaswmin/nix
[club]: https://1kb.club/
[ruby]: https://franzejr.github.io/best-ruby/
[jekyll]: https://jekyllrb.com/
[gh-pages]: https://pages.github.com/
[gh-actions]: https://github.com/features/actions
[gfm]: https://github.github.com/gfm/
[rouge]: https://github.com/rouge-ruby/rouge
[pygments]: https://pygments.org/
[file-rb]: https://github.com/nicholaswmin/nix/blob/main/nix.rb
[fi-join]: https://ruby-doc.org/3.3.2/File.html#method-c-join
[ruby]: https://ruby-doc.org/3.3.5/
[download]: https://github.com/nicholaswmin/nix/blob/main/nix.rb
[kiss]: https://en.wikipedia.org/wiki/KISS_principle#In_software_development
[corr]: https://en.wikipedia.org/wiki/Correctness_(computer_science)
[oop]: https://en.wikipedia.org/wiki/Object-oriented_programming
[njs]: https://en.wikipedia.org/wiki/Worse_is_better
[lob]: https://htmx.org/essays/locality-of-behaviour
[worse-better]: https://dreamsongs.com/Files/IsWorseReallyBetter.pdf
[worse-is-better]: https://curtsinger.cs.grinnell.edu/teaching/2021S1/CSC213/files/worse_is_better.pdf
[rpg]: https://en.wikipedia.org/wiki/Richard_P._Gabriel
[chest-fence]: https://fs.blog/chestertons-fence/
[polymor]: https://en.wikipedia.org/wiki/Subtyping
[encapsu]: https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)