summaryrefslogtreecommitdiff
path: root/README.md
blob: acb50ab90bbb8059ad42ebfbeafcbb0d4237a6ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# flexo

*alpha quality software*

The Common Lisp, interactive system for static site generation.

For an example of a site made with flexo, see [my site's source](https://github.com/cbeo/hyperthings.garden)

The idea is this:

1. You make a recipe that builds your site. It typically has two parts:
  - The recipe first adds and classifies content resources, which are usually files on disk
  - The recipie then uses those resources to build "artifacts", which are mostly pages.
2. You then pass the recipie to a function that builds and publishes the site.

## A Basic Example

``` lisp 
;; A recipe. Makes a single page.
(defun my-site-recipe () 
  (page-with-main-layout "/index.html" 'index-page-content))
  
```

The above recipe is a function of zero arguments. It will be called by
builder functions in a special context where a few dynamic variables
are approrpiately assigned. 

It should be noted that **recipies can be nested**: you can call one recipe inside another. If your site is large, you 
may benefit from developing portions of the site in their own recipes which are themselves composed
in a single top-level recipe.

The `page-with-main-layout` is a template defined like so:

``` lisp

(define-spinneret-template page-with-main-layout
    (url content-view)
  (:html
   (:head
    (:meta :name "viewport" :content "width=device-width, initial-scale=1")
   (:body
    (:div :class "main-layout"
          (funcall content-view)))))
          
```

Notice that the template is defined to accept a functional argument called `content-view`.  
When we called `page-with-main-layout` in our recipe above, we passed `index-page-content` 
as the `content-view` argument.  This is just a function that prints to the spinneret html stream.

``` lisp

(defun index-page-content ()
  (with-html
    (:h2 :class "center" "A Heading")
    (:p "Some text.")))

```

Right now, macros to define page templates are exclusively using spinneret, but there is 
no reason that other systems cannot be added.

You can then build the site to disk by doing:

``` lisp 

(build-and-publish 
   'my-site-recipe 
   #P"/home/me/sites/my-site" ; where files end up
   "https://example.com")     ; the host where this is intended to be served

```

But while you are developing a site, you're unlikely to use
`build-and-publish` very much.  Flexo is mainly for interactive
development of static sites:


## Interactive development

The real benefit of flexo is interactive development.

If you run the function 

    (hack-on 'my-site-recipe #P/tmp/flexo-hack-space/" :port 4242)
    
The you can do things like add new resources and recompile the functions that build artifact and the site will automatically redisplay.


## Future development

- Separate `spinneret`, `LASS`, and `parenscript` template macros into their own packages
- Document the CLOS Protocol that Flexo uses, including how to extend it to:
  - Make your own artifact classes
  - Make your own content classes
  - Make your own publication location classes (only publishing to disk is presently supported)
- Add content as:
  - Entire separate document trees for importing "subsites"
  - Database Queries as resources, not just files
  - API calls as resources, not just files