syntropy 0.3 → 0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -2
- data/CHANGELOG.md +14 -0
- data/README.md +30 -11
- data/TODO.md +135 -0
- data/bin/syntropy +3 -3
- data/cmd/setup/template/site/.gitignore +57 -0
- data/cmd/setup/template/site/Dockerfile +32 -0
- data/cmd/setup/template/site/Gemfile +3 -0
- data/cmd/setup/template/site/README.md +0 -0
- data/cmd/setup/template/site/bin/console +0 -0
- data/cmd/setup/template/site/bin/restart +0 -0
- data/cmd/setup/template/site/bin/server +0 -0
- data/cmd/setup/template/site/bin/start +0 -0
- data/cmd/setup/template/site/bin/stop +0 -0
- data/cmd/setup/template/site/docker-compose.yml +51 -0
- data/cmd/setup/template/site/proxy/Dockerfile +5 -0
- data/cmd/setup/template/site/proxy/etc/Caddyfile +7 -0
- data/cmd/setup/template/site/proxy/etc/tls_auto +2 -0
- data/cmd/setup/template/site/proxy/etc/tls_cloudflare +4 -0
- data/cmd/setup/template/site/proxy/etc/tls_custom +1 -0
- data/cmd/setup/template/site/proxy/etc/tls_selfsigned +1 -0
- data/cmd/setup/template/site/site/_layout/default.rb +11 -0
- data/cmd/setup/template/site/site/about.md +6 -0
- data/cmd/setup/template/site/site/articles/cage.rb +29 -0
- data/cmd/setup/template/site/site/articles/index.rb +3 -0
- data/cmd/setup/template/site/site/assets/css/style.css +40 -0
- data/cmd/setup/template/site/site/assets/img/syntropy.png +0 -0
- data/cmd/setup/template/site/site/index.rb +15 -0
- data/docker-compose.yml +51 -0
- data/lib/syntropy/app.rb +112 -134
- data/lib/syntropy/errors.rb +16 -2
- data/lib/syntropy/file_watch.rb +5 -4
- data/lib/syntropy/module.rb +26 -5
- data/lib/syntropy/request_extensions.rb +96 -0
- data/lib/syntropy/router.rb +208 -0
- data/lib/syntropy/rpc_api.rb +26 -9
- data/lib/syntropy/side_run.rb +46 -0
- data/lib/syntropy/version.rb +1 -1
- data/lib/syntropy.rb +15 -49
- data/syntropy.gemspec +1 -1
- data/test/app/baz.rb +3 -0
- data/test/app_custom/_site.rb +3 -0
- data/test/test_app.rb +96 -51
- data/test/test_file_watch.rb +4 -4
- data/test/test_router.rb +90 -0
- data/test/test_side_run.rb +43 -0
- data/test/test_validation.rb +1 -1
- metadata +34 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f125135bc3ed83c1050467241f48caf366600fead1d75db79455038e42e311a
|
4
|
+
data.tar.gz: ee9bd2bbf906eea9c90481ecdf643126285f65f63fe66a3f2b4f3050893e7c28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bdce31c490701521d73829c02e1193fcd0da399b1e6186066ad5d6ecfa067dc143941300bf670fa4b447d5d5c177e903fa273d9d6d5bbfa2319ec0c74fd2678
|
7
|
+
data.tar.gz: 7b5eddf105f8654f379bf1d7f52948b713ee342dbd97eb1896e28b618b442ccf33c716d27a7f67c21cfd2c65f610b5c9677cd5e4faa0e777b8f727552628865c
|
data/.rubocop.yml
CHANGED
@@ -7,8 +7,16 @@ AllCops:
|
|
7
7
|
- "test/**/*.rb"
|
8
8
|
- "examples/**/*.rb"
|
9
9
|
- "Gemfile*"
|
10
|
-
|
11
|
-
|
10
|
+
Style/LambdaCall:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Style/BlockDelimiters:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Style/Semicolon:
|
17
|
+
Exclude:
|
18
|
+
- cmd/setup/template/site/site/articles/cage.rb
|
19
|
+
|
12
20
|
# Style/ModuleFunction:
|
13
21
|
# Enabled: false
|
14
22
|
# Style/RegexpLiteral:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.5 2025-07-05
|
2
|
+
|
3
|
+
- Refactor App class to use Router
|
4
|
+
- Refactor routing functionality into separate Router class
|
5
|
+
- Add support for _site.rb file
|
6
|
+
|
7
|
+
## 0.4 2025-07-03
|
8
|
+
|
9
|
+
- Improve errors API
|
10
|
+
- Add HTTP method validation
|
11
|
+
- Refactor Qeweney::Request extensions
|
12
|
+
- Add side_run API for running tasks on a side thread
|
13
|
+
- Add support for rendering markdown with layout
|
14
|
+
|
1
15
|
## 0.3 2025-06-25
|
2
16
|
|
3
17
|
- Implement module reloading on file change
|
data/README.md
CHANGED
@@ -22,22 +22,42 @@
|
|
22
22
|
| Syntropy: A tendency towards complexity, structure, order, organization of
|
23
23
|
ever more advantageous and orderly patterns.
|
24
24
|
|
25
|
-
Syntropy is a
|
25
|
+
Syntropy is a web framework for building multi-page and single-page apps.
|
26
26
|
Syntropy uses file tree-based routing, and provides controllers for a number of
|
27
27
|
common patterns, such as a SPA with client-side rendering, a standard
|
28
28
|
server-rendered MPA, a REST API etc.
|
29
29
|
|
30
|
+
Syntropy also provides tools for working with lists of items represented as
|
31
|
+
files (ala Jekyll and other static site generators), allowing you to build
|
32
|
+
read-only apps (such as a markdown blog) without using a database.
|
33
|
+
|
34
|
+
For interactive apps, Syntropy provides basic tools for working with SQLite
|
35
|
+
databases in a concurrent environment.
|
36
|
+
|
37
|
+
Syntropy is based on:
|
38
|
+
|
39
|
+
- [UringMachine](https://github.com/digital-fabric/uringmachine) - a lean mean
|
40
|
+
[io_uring](https://unixism.net/loti/what_is_io_uring.html) machine for Ruby.
|
41
|
+
- [TP2](https://github.com/noteflakes/tp2) - an io_uring-based web server for
|
42
|
+
concurrent Ruby apps.
|
43
|
+
- [Qeweney](https://github.com/digital-fabric/qeweney) a uniform interface for
|
44
|
+
working with HTTP requests and responses.
|
45
|
+
- [Papercraft](https://github.com/digital-fabric/papercraft) HTML templating
|
46
|
+
with plain Ruby.
|
47
|
+
- [Extralite](https://github.com/digital-fabric/extralite) a fast and innovative
|
48
|
+
SQLite wrapper for Ruby.
|
49
|
+
|
30
50
|
## Routing
|
31
51
|
|
32
|
-
|
33
|
-
|
52
|
+
Syntropy routes request by following the tree structure of the Syntropy app. A
|
53
|
+
simple example:
|
34
54
|
|
35
55
|
```
|
36
56
|
site/
|
37
57
|
├ _layout/
|
38
58
|
| └ default.rb
|
39
59
|
├ _articles/
|
40
|
-
| └ 2025-
|
60
|
+
| └ 2025-01-01-hello_world.md
|
41
61
|
├ api/
|
42
62
|
| └ v1.rb
|
43
63
|
├ assets/
|
@@ -50,9 +70,8 @@ site/
|
|
50
70
|
└ robots.txt
|
51
71
|
```
|
52
72
|
|
53
|
-
|
54
|
-
|
55
|
-
Ruby code.
|
73
|
+
Syntropy knows how to serve static asset files (CSS, JS, images...) as well as
|
74
|
+
render markdown files and run modules written in Ruby.
|
56
75
|
|
57
76
|
## What does a Syntropic Ruby module look like?
|
58
77
|
|
@@ -67,7 +86,7 @@ def articles
|
|
67
86
|
Syntropy.stamped_file_entries('/_articles')
|
68
87
|
end
|
69
88
|
|
70
|
-
@@layout.apply(title: 'archive') {
|
89
|
+
export @@layout.apply(title: 'archive') {
|
71
90
|
div {
|
72
91
|
ul {
|
73
92
|
articles.each { |article|
|
@@ -98,8 +117,8 @@ class APIV1 < Syntropy::RPCAPI
|
|
98
117
|
end
|
99
118
|
end
|
100
119
|
|
101
|
-
APIV1
|
120
|
+
export APIV1
|
102
121
|
```
|
103
122
|
|
104
|
-
Basically, the
|
105
|
-
responds to the request.
|
123
|
+
Basically, the exported value can be a template, a callable or a class that
|
124
|
+
responds to the request.
|
data/TODO.md
CHANGED
@@ -0,0 +1,135 @@
|
|
1
|
+
- Refactor routing code into a separate Router class.
|
2
|
+
- The Router class is in charge of:
|
3
|
+
- caching routes
|
4
|
+
- loading modules
|
5
|
+
- unloading modules on file change
|
6
|
+
- calculating middleware for routes
|
7
|
+
- middleware is defined in `_hook.rb` modules
|
8
|
+
- interface: ->(req, next)
|
9
|
+
- a special case for handling errors is `_error.rb`
|
10
|
+
- interface: ->(req, err)
|
11
|
+
- dispatching routes
|
12
|
+
- error handling:
|
13
|
+
- on uncaught error, if an `_error.rb` file exists in the same directory
|
14
|
+
or up the file tree
|
15
|
+
- middleware:
|
16
|
+
- a closure is created from the composition of the different hooks
|
17
|
+
defined, from the route's directory and up the file
|
18
|
+
- error handlers and middleware closures are cached as part of the route's
|
19
|
+
entry
|
20
|
+
- on file change for any _hook.rb or _error.rb files, all route entries in
|
21
|
+
the corresponding subtree are invalidated
|
22
|
+
|
23
|
+
|
24
|
+
- Middleware
|
25
|
+
|
26
|
+
```Ruby
|
27
|
+
# site/_hook.rb
|
28
|
+
export ->(req, &app) do
|
29
|
+
app.call(req)
|
30
|
+
rescue Syntropy::Error => e
|
31
|
+
render_error_page(req, e.http_status)
|
32
|
+
end
|
33
|
+
|
34
|
+
# an alternative, at least for errors is a _error.rb file:
|
35
|
+
# site/_error.rb
|
36
|
+
# Just a normal callable:
|
37
|
+
#
|
38
|
+
export ->(req, err) do
|
39
|
+
render_error_page(req, err.http_status)
|
40
|
+
end
|
41
|
+
|
42
|
+
# a _site.rb file can be used to wrap a whole app
|
43
|
+
# site/_site.rb
|
44
|
+
|
45
|
+
# this means we route according to the host header, with each
|
46
|
+
export Syntropy.route_by_host
|
47
|
+
|
48
|
+
# we can also rewrite requests:
|
49
|
+
rewriter = Syntropy
|
50
|
+
.select { it.host =~ /^tolkora\.(org|com)$/ }
|
51
|
+
.terminate { it.redirect_permanent('https://tolkora.net') }
|
52
|
+
|
53
|
+
# This is actuall a pretty interesting DSL design:
|
54
|
+
# a chain of operations that compose functions. So, we can select a
|
55
|
+
export rewriter.wrap(default_app)
|
56
|
+
|
57
|
+
# composing
|
58
|
+
export rewriter.wrap(Syntropy.some_custom_app.wrap(app))
|
59
|
+
|
60
|
+
# or maybe
|
61
|
+
export rewriter << some_other_middleware << app
|
62
|
+
```
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
- CLI tool for setting up a site repo:
|
68
|
+
|
69
|
+
```bash
|
70
|
+
# clone a newly created repo
|
71
|
+
~/repo$ git clone https://github.com/foo/bar
|
72
|
+
...
|
73
|
+
~/repo$ syntropy setup bar
|
74
|
+
|
75
|
+
(syntropy banner)
|
76
|
+
|
77
|
+
Setting up Syntropy project in /home/sharon/repo/bar:
|
78
|
+
|
79
|
+
bar/
|
80
|
+
bin/
|
81
|
+
start
|
82
|
+
stop
|
83
|
+
restart
|
84
|
+
console
|
85
|
+
server
|
86
|
+
docker-compose.yml
|
87
|
+
Dockerfile
|
88
|
+
Gemfile
|
89
|
+
proxy/
|
90
|
+
|
91
|
+
README.md
|
92
|
+
site/
|
93
|
+
_layout/
|
94
|
+
default.rb
|
95
|
+
_lib/
|
96
|
+
about.md
|
97
|
+
articles/
|
98
|
+
long-form.md
|
99
|
+
assets/
|
100
|
+
js/
|
101
|
+
css/
|
102
|
+
style.css
|
103
|
+
img/
|
104
|
+
syntropy.png
|
105
|
+
index.rb
|
106
|
+
```
|
107
|
+
|
108
|
+
- Some of the files might need templating, but we can maybe do without, or at
|
109
|
+
least make it as generic as possible.
|
110
|
+
|
111
|
+
- `syntropy setup` steps:
|
112
|
+
|
113
|
+
1. Verify existence of target directory
|
114
|
+
2. Copy files from Syntropy template to target directory
|
115
|
+
3. Do chmod +x for bin/*
|
116
|
+
4. Do bundle install in the target directory
|
117
|
+
5. Show some information with regard to how to get started working with the
|
118
|
+
repo
|
119
|
+
|
120
|
+
- `syntropy provision` steps:
|
121
|
+
|
122
|
+
1. Verify Ubuntu 22.x or higher
|
123
|
+
2. Install git, docker, docker-compose
|
124
|
+
|
125
|
+
- `syntropy deploy` steps:
|
126
|
+
|
127
|
+
1. Verify no uncommitted changes.
|
128
|
+
2. SSH to remote machine.
|
129
|
+
2.1. If not exists, clone repo
|
130
|
+
2.2. Otherwise, verify remote machine repo is on same branch as local repo
|
131
|
+
2.3. Do a git pull (what about credentials?)
|
132
|
+
2.4. If gem bundle has changed, do a docker compose build
|
133
|
+
2.5. If docker compose services are running, restart
|
134
|
+
2.6. Otherwise, start services
|
135
|
+
2.7. Verify service is running correctly
|
data/bin/syntropy
CHANGED
@@ -57,9 +57,9 @@ if !File.directory?(opts[:location])
|
|
57
57
|
end
|
58
58
|
|
59
59
|
|
60
|
-
|
61
|
-
opts[:machine] = UM.new
|
60
|
+
# We set Syntropy.machine so we can reference it from anywhere
|
61
|
+
opts[:machine] = Syntropy.machine = UM.new
|
62
62
|
opts[:logger] = opts[:logger] && TP2::Logger.new(opts[:machine], **opts)
|
63
63
|
|
64
|
-
app = Syntropy::App.
|
64
|
+
app = Syntropy::App.load(opts)
|
65
65
|
TP2.run(opts) { app.call(it) }
|
@@ -0,0 +1,57 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
# Ignore Byebug command history file.
|
17
|
+
.byebug_history
|
18
|
+
|
19
|
+
## Specific to RubyMotion:
|
20
|
+
.dat*
|
21
|
+
.repl_history
|
22
|
+
build/
|
23
|
+
*.bridgesupport
|
24
|
+
build-iPhoneOS/
|
25
|
+
build-iPhoneSimulator/
|
26
|
+
|
27
|
+
## Specific to RubyMotion (use of CocoaPods):
|
28
|
+
#
|
29
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
30
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
31
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
32
|
+
#
|
33
|
+
# vendor/Pods/
|
34
|
+
|
35
|
+
## Documentation cache and generated files:
|
36
|
+
/.yardoc/
|
37
|
+
/_yardoc/
|
38
|
+
/doc/
|
39
|
+
/rdoc/
|
40
|
+
|
41
|
+
## Environment normalization:
|
42
|
+
/.bundle/
|
43
|
+
/vendor/bundle
|
44
|
+
/lib/bundler/man/
|
45
|
+
|
46
|
+
# for a library or gem, you might want to ignore these files since the code is
|
47
|
+
# intended to run in multiple environments; otherwise, check them in:
|
48
|
+
# Gemfile.lock
|
49
|
+
# .ruby-version
|
50
|
+
# .ruby-gemset
|
51
|
+
|
52
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
53
|
+
.rvmrc
|
54
|
+
|
55
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
56
|
+
# .rubocop-https?--*
|
57
|
+
log
|
@@ -0,0 +1,32 @@
|
|
1
|
+
ARG RUBY_BASE_IMAGE=ruby:3.4.1-alpine
|
2
|
+
ARG GEM_CACHE_IMAGE=${RUBY_BASE_IMAGE}
|
3
|
+
|
4
|
+
# base image
|
5
|
+
FROM ${RUBY_BASE_IMAGE} AS base
|
6
|
+
RUN apk add --update sqlite-dev openssl-dev tzdata bash curl zip git
|
7
|
+
RUN apk add --update build-base
|
8
|
+
RUN gem install bundler:2.6.9
|
9
|
+
|
10
|
+
# gem cache
|
11
|
+
FROM ${GEM_CACHE_IMAGE} AS gem-cache
|
12
|
+
RUN mkdir -p /usr/local/bundle
|
13
|
+
|
14
|
+
FROM base AS gems
|
15
|
+
COPY --from=gem-cache /usr/local/bundle /usr/local/bundle
|
16
|
+
COPY Gemfile Gemfile.lock ./
|
17
|
+
RUN bundle install --jobs=4 --retry=5
|
18
|
+
|
19
|
+
# Final backend image
|
20
|
+
FROM base AS deploy
|
21
|
+
|
22
|
+
RUN adduser -D app
|
23
|
+
RUN chown app:app /home/app
|
24
|
+
WORKDIR /home/app
|
25
|
+
USER app
|
26
|
+
|
27
|
+
RUN mkdir -p /tmp
|
28
|
+
COPY --from=gems --chown=app:app /usr/local/bundle /usr/local/bundle
|
29
|
+
|
30
|
+
EXPOSE 1234
|
31
|
+
|
32
|
+
CMD ["bundle", "exec", "tp2", "."]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,51 @@
|
|
1
|
+
services:
|
2
|
+
backend:
|
3
|
+
build: .
|
4
|
+
privileged: true
|
5
|
+
restart: always
|
6
|
+
ports:
|
7
|
+
- 127.0.0.1:1234:1234
|
8
|
+
# expose:
|
9
|
+
# - 1234
|
10
|
+
volumes:
|
11
|
+
- .:/home/app
|
12
|
+
deploy:
|
13
|
+
# replicas: 1
|
14
|
+
resources:
|
15
|
+
limits:
|
16
|
+
memory: 500M
|
17
|
+
# restart: unless-stopped
|
18
|
+
logging:
|
19
|
+
driver: "json-file"
|
20
|
+
options:
|
21
|
+
max-size: "1M"
|
22
|
+
max-file: "10"
|
23
|
+
|
24
|
+
# healthcheck:
|
25
|
+
# test: "curl 'http://localhost:1234/?q=ping'"
|
26
|
+
# interval: "30s"
|
27
|
+
# timeout: "3s"
|
28
|
+
# start_period: "5s"
|
29
|
+
# retries: 3
|
30
|
+
|
31
|
+
proxy:
|
32
|
+
depends_on:
|
33
|
+
- backend
|
34
|
+
build:
|
35
|
+
context: ./proxy
|
36
|
+
dockerfile: Dockerfile
|
37
|
+
restart: always
|
38
|
+
volumes:
|
39
|
+
- ./proxy/etc/Caddyfile:/etc/caddy/Caddyfile
|
40
|
+
ports:
|
41
|
+
- "80:80"
|
42
|
+
- "443:443"
|
43
|
+
- "443:443/udp"
|
44
|
+
# env_file:
|
45
|
+
# - ./conf/caddy.env
|
46
|
+
# - ./conf/caddy_sensitive.env
|
47
|
+
logging:
|
48
|
+
driver: "json-file"
|
49
|
+
options:
|
50
|
+
max-size: "1M"
|
51
|
+
max-file: "10"
|
@@ -0,0 +1 @@
|
|
1
|
+
tls {$TLS_CUSTOM_CERT} {$TLS_CUSTOM_KEY}
|
@@ -0,0 +1 @@
|
|
1
|
+
tls internal
|
@@ -0,0 +1,29 @@
|
|
1
|
+
layout = import('_layout/default')
|
2
|
+
|
3
|
+
poem = [
|
4
|
+
" in ten\xA0", 'M', 'inutes',
|
5
|
+
' ', 'C', 'ome back: you will',
|
6
|
+
'have taught me chi', 'N', 'ese',
|
7
|
+
' (s', 'A', 'tie).',
|
8
|
+
' shall I ret', 'U', 'rn the favor?',
|
9
|
+
' ', 'G', 'ive you',
|
10
|
+
' ot', 'H', 'er lessons',
|
11
|
+
' (', 'T', 'ing!)?',
|
12
|
+
' ', 'O', 'r would you prefer',
|
13
|
+
' sile', 'N', 'ce?',
|
14
|
+
]
|
15
|
+
|
16
|
+
export layout.apply {
|
17
|
+
article(class: 'mesostic') {
|
18
|
+
h2 'For William McN. who studied with Ezra Pound'
|
19
|
+
|
20
|
+
content {
|
21
|
+
span(_for: poem) { text it }
|
22
|
+
}
|
23
|
+
|
24
|
+
author {
|
25
|
+
span "-\xA0"
|
26
|
+
a 'John cage', href: 'https://en.wikipedia.org/wiki/John_Cage'
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
body {
|
2
|
+
font-family: sans-serif;
|
3
|
+
}
|
4
|
+
|
5
|
+
article.mesostic {
|
6
|
+
width: 600px;
|
7
|
+
margin: 2em auto;
|
8
|
+
font-size: 1.4em;
|
9
|
+
|
10
|
+
* {
|
11
|
+
font-family: monospace;
|
12
|
+
}
|
13
|
+
|
14
|
+
h2 {
|
15
|
+
text-align: center;
|
16
|
+
}
|
17
|
+
|
18
|
+
content {
|
19
|
+
display: grid;
|
20
|
+
margin: 2em 0;
|
21
|
+
grid-template-columns: 1fr auto 1fr;
|
22
|
+
|
23
|
+
span {
|
24
|
+
display: inline-block;
|
25
|
+
}
|
26
|
+
span:nth-child(3n + 1) {
|
27
|
+
text-align: right;
|
28
|
+
}
|
29
|
+
|
30
|
+
span:nth-child(3n + 2) {
|
31
|
+
text-align: center;
|
32
|
+
font-weight: bold;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
author {
|
37
|
+
display: block;
|
38
|
+
text-align: right;
|
39
|
+
}
|
40
|
+
}
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
layout = import('_layout/default')
|
2
|
+
|
3
|
+
export layout.apply {
|
4
|
+
h1 'Hello from Syntropy'
|
5
|
+
p {
|
6
|
+
span "Here's an "
|
7
|
+
a 'about', href: 'about'
|
8
|
+
span ' page.'
|
9
|
+
}
|
10
|
+
p {
|
11
|
+
span "Here's an "
|
12
|
+
a 'article', href: 'articles/cage'
|
13
|
+
span ' page.'
|
14
|
+
}
|
15
|
+
}
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
services:
|
2
|
+
backend:
|
3
|
+
build: .
|
4
|
+
privileged: true
|
5
|
+
restart: always
|
6
|
+
ports:
|
7
|
+
- 127.0.0.1:1234:1234
|
8
|
+
# expose:
|
9
|
+
# - 1234
|
10
|
+
volumes:
|
11
|
+
- .:/home/app
|
12
|
+
deploy:
|
13
|
+
# replicas: 1
|
14
|
+
resources:
|
15
|
+
limits:
|
16
|
+
memory: 500M
|
17
|
+
# restart: unless-stopped
|
18
|
+
logging:
|
19
|
+
driver: "json-file"
|
20
|
+
options:
|
21
|
+
max-size: "1M"
|
22
|
+
max-file: "10"
|
23
|
+
|
24
|
+
# healthcheck:
|
25
|
+
# test: "curl 'http://localhost:1234/?q=ping'"
|
26
|
+
# interval: "30s"
|
27
|
+
# timeout: "3s"
|
28
|
+
# start_period: "5s"
|
29
|
+
# retries: 3
|
30
|
+
|
31
|
+
proxy:
|
32
|
+
depends_on:
|
33
|
+
- backend
|
34
|
+
build:
|
35
|
+
context: ./proxy
|
36
|
+
dockerfile: Dockerfile
|
37
|
+
restart: always
|
38
|
+
volumes:
|
39
|
+
- ./proxy/etc/Caddyfile:/etc/caddy/Caddyfile
|
40
|
+
ports:
|
41
|
+
- "80:80"
|
42
|
+
- "443:443"
|
43
|
+
- "443:443/udp"
|
44
|
+
# env_file:
|
45
|
+
# - ./conf/caddy.env
|
46
|
+
# - ./conf/caddy_sensitive.env
|
47
|
+
logging:
|
48
|
+
driver: "json-file"
|
49
|
+
options:
|
50
|
+
max-size: "1M"
|
51
|
+
max-file: "10"
|