Skip to content

Commit 4ebbc65

Browse files
committed
Add agent context.
1 parent c15e3c3 commit 4ebbc65

File tree

10 files changed

+589
-2
lines changed

10 files changed

+589
-2
lines changed

bake.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
# @parameter version [String] The new version number.
99
def after_gem_release_version_increment(version)
1010
context["releases:update"].call(version)
11-
context["utopia:project:readme:update"].call
11+
context["utopia:project:update"].call
1212
end

context/getting-started.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Getting Started
2+
3+
This guide explains how to set up a `utopia` website for local development and deployment.
4+
5+
## Installation
6+
7+
Utopia is built on Ruby and Rack. Therefore, Ruby (suggested 2.0+) should be installed and working. Then, to install `utopia` and all required dependencies, run:
8+
9+
~~~ bash
10+
$ gem install utopia
11+
~~~
12+
13+
### Atom Integration
14+
15+
Utopia uses [Trenni](https://github.com/ioquatix/trenni) for templates and it has a syntax slightly different from ERB. However, there is a [package for Atom](https://atom.io/packages/language-trenni) which provides accurate syntax highlighting.
16+
17+
## Your First Page
18+
19+
To setup the default site, create a directory (typically the hostname of the site you want to create) and use the `bake utopia:site:create` command:
20+
21+
~~~ bash
22+
$ mkdir www.example.com
23+
$ cd www.example.com
24+
$ bake --gem utopia utopia:site:create
25+
$ bake utopia:development
26+
~~~
27+
28+
You will now have a basic template site running on `https://localhost:9292`.
29+
30+
### Welcome Page
31+
32+
Utopia includes a redirection middleware to redirect all root-level requests to a given URI. The default being `/welcome/index`:
33+
34+
```ruby
35+
# in config.ru
36+
37+
use Utopia::Redirection::Rewrite,
38+
"/" => "/welcome/index"
39+
```
40+
41+
The content for this page is stored in `pages/welcome/index.xnode`. The format of this page is a subset of HTML5 - open and close tags are strictly enforced.
42+
43+
There are several special tags which are used for creating modular content. The most common one is the outer `<content:page>` tag. Utopia uses the name `page` to lookup the file-system hierarchy. First, it looks for `/welcome/_page.xnode`, and then it looks for `/_page.xnode` which it finds. This page template includes a special `<utopia:content/>` tag which is replaced with the inner body of the `<content:page>` tag. This recursive lookup is the heart of Utopia.
44+
45+
### Links
46+
47+
Utopia is a content-centric web application platform. It leverages the file-system to provide a mapping between logical resources and files on disk. The primary mode of mapping incoming requests to specific nodes (content) is done using the `links.yaml` file.
48+
49+
The links file associates metadata with node names for a given directory. This can include things like redirects, titles, descriptions, etc. You can add any metadata you like, to support your specific use-case. The primary use of the links files is to provide site structure, e.g. menus. In addition, they can function as a rudimentary data-store for static information, e.g. a list of applications (each with it's own page), a list of features, etc.
50+
51+
You'll notice that there is a file `/links.yaml`. This file contains important metadata relating to the `errors` subdirectory. As we don't want these nodes showing up in a top level menu, we mark them as `display: false`
52+
53+
~~~ yaml
54+
errors:
55+
display: false
56+
~~~
57+
58+
## Testing
59+
60+
Utopia websites include a default set of tests using `sus`. These specs can test against the actual running website.
61+
62+
~~~ bash
63+
$ sus
64+
65+
1 samples: 1x 200. 3703.7 requests per second. S/D: 0.000µs.
66+
1 passed out of 1 total (2 assertions)
67+
🏁 Finished in 247.4ms; 8.085 assertions per second.
68+
~~~
69+
70+
The website test will spider all pages on your site and report any broken links as failures.
71+
72+
### Coverage
73+
74+
The [covered](https://github.com/socketry/covered) gem is used for providing source code coverage information.
75+
76+
~~~ bash
77+
$ COVERAGE=BriefSummary rspec
78+
79+
website
80+
1 samples: 1x 200. 67.53 requests per second. S/D: 0.000µs.
81+
should be responsive
82+
83+
* 5 files checked; 33/46 lines executed; 71.74% covered.
84+
85+
Least Coverage:
86+
pages/_page.xnode: 6 lines not executed!
87+
config.ru: 4 lines not executed!
88+
pages/welcome/index.xnode: 2 lines not executed!
89+
pages/_heading.xnode: 1 lines not executed!
90+
91+
Finished in 1.82 seconds (files took 0.51845 seconds to load)
92+
1 example, 0 failures
93+
~~~

context/index.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Automatically generated context index for Utopia::Project guides.
2+
# Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
3+
---
4+
description: Utopia is a framework for building dynamic content-driven websites.
5+
metadata:
6+
documentation_uri: https://socketry.github.io/utopia/
7+
funding_uri: https://github.com/sponsors/ioquatix/
8+
source_code_uri: https://github.com/socketry/utopia.git
9+
files:
10+
- path: getting-started.md
11+
title: Getting Started
12+
description: This guide explains how to set up a `utopia` website for local development
13+
and deployment.
14+
- path: middleware.md
15+
title: Middleware
16+
description: This guide gives an overview of the different Rack middleware used
17+
by Utopia.
18+
- path: server-setup.md
19+
title: Server Setup
20+
description: This guide explains how to deploy a `utopia` web application.
21+
- path: integrating-with-javascript.md
22+
title: Installing JavaScript Libraries
23+
description: Utopia integrates with Yarn and provides a [bake task](https://github.com/ioquatix/bake)
24+
to simplify deployment packages distributed using `yarn` that implement the `dist`
25+
sub-directory convention.
26+
- path: what-is-xnode.md
27+
title: What is XNode?
28+
description: This guide explains the `xnode` view layer and how it can be used to
29+
build efficient websites.
30+
- path: updating-utopia.md
31+
title: Updating Utopia
32+
description: This guide explains how to update existing `utopia` websites.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Installing JavaScript Libraries
2+
3+
Utopia integrates with Yarn and provides a [bake task](https://github.com/ioquatix/bake) to simplify deployment packages distributed using `yarn` that implement the `dist` sub-directory convention.
4+
5+
## Installing Yarn
6+
7+
If you don't already have yarn installed, make sure you have npm installed and then run the following command:
8+
9+
```bash
10+
$ sudo npm install -g yarn
11+
```
12+
13+
## Installing jQuery
14+
15+
Firstly, ensure your project has a `package.json` file:
16+
17+
```bash
18+
$ yarn init
19+
```
20+
21+
Then install jquery using `yarn`:
22+
23+
```bash
24+
$ yarn add jquery
25+
```
26+
27+
Copy the distribution scripts to `public/_components`:
28+
29+
```bash
30+
$ bundle exec bake utopia:node:update
31+
```
32+
33+
Then add the appropriate `<script>` tags to `pages/_page.xnode`:
34+
35+
```html
36+
<script type="text/javascript" src="/_components/jquery/jquery.min.js"></script>
37+
```
38+
39+
## Using JavaScript
40+
41+
You can use JavaScript by embedding it directly into your HTML, or by creating a JavaScript source file and referencing that.
42+
43+
### Embedding Code
44+
45+
In your HTML view:
46+
47+
```trenni
48+
<html>
49+
<body>
50+
<script type="text/javascript">
51+
//<![CDATA[
52+
console.log("Hello World")
53+
//]]>
54+
</script>
55+
</body>
56+
</html>
57+
```
58+
59+
### External Script
60+
61+
In `script.js`:
62+
63+
```javascript
64+
console.log("Hello World")
65+
```
66+
67+
In your HTML view:
68+
69+
```trenni
70+
<html>
71+
<body>
72+
<script type="text/javascript" src="script.js"></script>
73+
</body>
74+
</html>
75+
```

context/middleware.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Middleware
2+
3+
This guide gives an overview of the different Rack middleware used by Utopia.
4+
5+
## Static
6+
7+
The {ruby Utopia::Static} middleware services static files efficiently. By default, it works with `Rack::Sendfile` and supports `ETag` based caching. Normally, you'd prefer to put static files into `public/_static` but it's also acceptable to put static content into `pages/` if it makes sense.
8+
9+
~~~ ruby
10+
use Utopia::Static,
11+
# The root path to serve files from:
12+
root: "path/to/root",
13+
# The mime-types to recognize/serve:
14+
types: [:default, :xiph],
15+
# Cache-Control header for files:
16+
cache_control: 'public, max-age=7200'
17+
~~~
18+
19+
## Redirection
20+
21+
The {ruby Utopia::Redirection} middleware is used for redirecting requests based on patterns and status codes.
22+
23+
~~~ ruby
24+
# String (fast hash lookup) rewriting:
25+
use Utopia::Redirection::Rewrite,
26+
'/' => '/welcome/index'
27+
28+
# Redirect directories (e.g. /) to an index file (e.g. /index):
29+
use Utopia::Redirection::DirectoryIndex,
30+
index: 'index.html'
31+
32+
# Redirect (error) status codes to actual pages:
33+
use Utopia::Redirection::Errors,
34+
404 => '/errors/file-not-found'
35+
~~~
36+
37+
## Localization
38+
39+
The {ruby Utopia::Localization} middleware provides non-intrusive localization on top of the controller and view layers. The middleware uses the `accept-language` header to guess the preferred locale out of the given options. If a request path maps to a resource, that resource is returned. Otherwise, a non-localized request is made.
40+
41+
~~~ ruby
42+
use Utopia::Localization,
43+
:default_locale => 'en',
44+
:locales => ['en', 'de', 'ja', 'zh']
45+
~~~
46+
47+
To localize a specific `xnode`, append the locale as a postfix:
48+
49+
~~~
50+
pages/index.xnode
51+
pages/index.de.xnode
52+
pages/index.ja.xnode
53+
pages/index.zh.xnode
54+
~~~
55+
56+
You can also access the current locale in the view via {ruby Utopia::Content::Node::Context#localization}.
57+
58+
## Controller
59+
60+
The {ruby Utopia::Controller} middleware provides flexible nested controllers with efficient behaviour. Controllers are nested in the `pages` directory and are matched against the incoming request path recursively, from outer most to inner most.
61+
62+
```ruby
63+
use Utopia::Controller,
64+
# The root directory where `controller.rb` files can be found.
65+
root: "path/to/root",
66+
# The base class to use for all controllers:
67+
base: Utopia::Controller::Base
68+
```
69+
70+
A controller is a file within the specified root directory (typically `pages`) with the name `controller.rb`. This code is dynamically loaded into an anonymous class and executed. The default controller has only a single function:
71+
72+
```ruby
73+
def passthrough(request, path)
74+
# Call one of:
75+
76+
# This will cause the middleware to generate a response.
77+
# def respond!(response)
78+
79+
# This will cause the controller to skip the request.
80+
# def ignore!
81+
82+
# Request relative redirect. Respond with a redirect to the given target.
83+
# def redirect! (target, status = 302)
84+
85+
# Controller relative redirect.
86+
# def goto!(target, status = 302)
87+
88+
# Respond with an error which indiciates some kind of failure.
89+
# def fail!(error = 400, message = nil)
90+
91+
# Succeed the request and immediately respond.
92+
# def succeed!(status: 200, headers: {}, **options)
93+
# options may include content: string or body: Enumerable (as per Rack specifications
94+
95+
suceed!
96+
end
97+
```
98+
99+
The controller layer can do more complex operations by prepending modules into it.
100+
101+
```ruby
102+
prepend Rewrite, Actions
103+
104+
# Extracts an Integer
105+
rewrite.extract_prefix id: Integer do
106+
@user = User.find_by_id(@id)
107+
end
108+
109+
on "edit" do |request, path|
110+
if request.post?
111+
@user.update_attributes(request[:user])
112+
end
113+
end
114+
115+
otherwise do |request, path|
116+
# Executed if no specific named actions were executed.
117+
succeed!
118+
end
119+
```
120+
121+
The incoming path is relative to the path of the controller itself.
122+
123+
## Content
124+
125+
The {ruby Utopia::Content} middleware parses XML-style templates with using attributes provided by the controller layer. Dynamic tags can be used to build modular content.
126+
127+
~~~ ruby
128+
use Utopia::Content
129+
~~~
130+
131+
A basic template `create.xnode` looks something like:
132+
133+
~~~trenni
134+
<content:page>
135+
<content:heading>Create User</content:heading>
136+
<form action="#">
137+
<input name="name" />
138+
<input type="submit" />
139+
</form>
140+
</content:page>
141+
~~~
142+
143+
This template would typically be designed with supporting `_page.xnode` and `_heading.xnode` in the same directory or, more typically, somewhere further up the directory hierarchy.
144+
145+
## Session
146+
147+
The {ruby Utopia::Session} middleware provides session storage using encrypted client-side cookies. The session management uses symmetric private key encryption to store data on the client and avoid tampering.
148+
149+
```ruby
150+
use Utopia::Session,
151+
expires_after: 3600 * 24,
152+
# The private key is retried from the `environment.yaml` file:
153+
secret: UTOPIA.secret_for(:session),
154+
secure: true
155+
```
156+
157+
All session data is stored on the client, but it's encrypted with a salt and the secret key. It is impossible for the client to decrypt the data without the secret stored on the server.

0 commit comments

Comments
 (0)