Commit
Author: Kevin Schoon [me@kevinschoon.com]
Hash: 6f536fae4e5481a0d713c250eabf117da524f171
Timestamp: Sat, 06 Jan 2024 13:42:58 +0000 (1 year ago)

+190 -30 +/-19 browse
add patch support with highlighting, misc mail updates
1diff --git a/ayllu-mail/src/main.rs b/ayllu-mail/src/main.rs
2index e09101b..67cf6a6 100644
3--- a/ayllu-mail/src/main.rs
4+++ b/ayllu-mail/src/main.rs
5 @@ -1,11 +1,19 @@
6- use std::io::stdout;
7+ use std::io::{stdin, stdout, Read, Write};
8 use std::path::PathBuf;
9+ use std::process::{Command as SystemCommand, Stdio};
10 use std::str::FromStr;
11
12+ use anyhow::{format_err, Error, Result};
13 use clap::{arg, Command, CommandFactory, Parser, Subcommand};
14 use clap_complete::{generate, Generator, Shell};
15+ use mailpot::{
16+ melib::Envelope,
17+ queue::{Queue, QueueEntry},
18+ transaction::TransactionBehavior,
19+ Connection,
20+ };
21 use tokio::{runtime::Builder as TokioBuilder, task::LocalSet};
22- use tracing::Level;
23+ use tracing::{log, Level};
24
25 mod config;
26 mod declarative;
27 @@ -37,6 +45,10 @@ enum Commands {
28 },
29 /// run the rpc server and mailing list manager
30 Serve {},
31+ /// post a new message into the mail queue from stdin
32+ Post {},
33+ /// send all queued messages to their recipients
34+ Send {},
35 }
36
37 fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
38 @@ -71,6 +83,77 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
39 .await
40 })?;
41 }
42+ Commands::Post {} => {
43+ let mut input = String::new();
44+ stdin().read_to_string(&mut input)?;
45+ let envelope = Envelope::from_bytes(input.as_bytes(), None)?;
46+ let mut db = Connection::open_or_create_db(ayllu_config.mailpot_config())?.trusted();
47+ let tx = db.transaction(TransactionBehavior::Exclusive)?;
48+ tx.post(&envelope, input.as_bytes(), false)?;
49+ tx.commit()?;
50+ }
51+ Commands::Send {} => {
52+ let mut db = Connection::open_or_create_db(ayllu_config.mailpot_config())?.trusted();
53+ let tx = db.transaction(TransactionBehavior::Exclusive)?;
54+ let messages = tx.queue(Queue::Out)?;
55+ let mut failed: Vec<QueueEntry> = Vec::with_capacity(messages.len());
56+ fn submit(cmd: &str, msg: &QueueEntry) -> Result<()> {
57+ let mut child = SystemCommand::new("sh")
58+ .arg("-c")
59+ .arg(cmd)
60+ .env("TO_ADDRESS", msg.to_addresses.clone())
61+ .stdout(Stdio::piped())
62+ .stdin(Stdio::piped())
63+ .stderr(Stdio::piped())
64+ .spawn()?;
65+ let mut stdin = child
66+ .stdin
67+ .take()
68+ .ok_or_else(|| format_err!("failed to attach to stdin"))?;
69+
70+ let builder = std::thread::Builder::new();
71+
72+ std::thread::scope(|s| {
73+ let handler = builder.spawn_scoped(s, move || {
74+ stdin
75+ .write_all(&msg.message)
76+ .expect("Failed to write to stdin");
77+ })?;
78+
79+ handler.join().map_err(|_| {
80+ format_err!(
81+ "Could not join with IPC communication thread for SMTP ShellCommand \
82+ process"
83+ )
84+ })?;
85+ let result = child.wait_with_output()?;
86+ if result.status.success() == false {
87+ return Err(format_err!(
88+ "sendmail proccess failed with exit code: {:?}\n{}",
89+ result.status.code(),
90+ String::from_utf8(result.stderr).unwrap()
91+ ));
92+ }
93+ Ok::<(), Error>(())
94+ })?;
95+ Ok(())
96+ }
97+ for message in messages {
98+ if let Err(err) = submit(&ayllu_config.mail.sendmail_command, &message) {
99+ log::error!(
100+ "error sending message: {}\n{}",
101+ message.message_id,
102+ err.to_string()
103+ );
104+ failed.push(message.0);
105+ }
106+ }
107+ for mut message in failed {
108+ message.queue = Queue::Deferred;
109+ tx.insert_to_queue(message)?;
110+ }
111+ tx.commit()?;
112+ }
113 }
114
115 Ok(())
116 diff --git a/ayllu-mail/src/server.rs b/ayllu-mail/src/server.rs
117index 9822a1c..6f3664d 100644
118--- a/ayllu-mail/src/server.rs
119+++ b/ayllu-mail/src/server.rs
120 @@ -1,6 +1,5 @@
121- use std::collections::HashMap;
122+ use std::borrow::Cow;
123 use std::error::Error as StdError;
124- use std::sync::{Arc, RwLock};
125
126 use anyhow::{format_err, Result};
127 use capnp::{capability::Promise, Error as CapnpError};
128 @@ -9,8 +8,7 @@ use mailpot::{
129 models::{DbVal, Post},
130 Connection, Error as MailpotError,
131 };
132- use melib::{thread::Threads, Envelope, EnvelopeHash};
133- use tracing::log;
134+ use melib::Envelope;
135
136 use crate::config::Config;
137 use ayllu_api::mail_capnp::server::{
138 @@ -19,6 +17,10 @@ use ayllu_api::mail_capnp::server::{
139 };
140 use ayllu_rpc::Server as RpcHelper;
141
142+ fn is_patch(subject: &str) -> bool {
143+ subject.contains("[PATCH]") || subject.contains("[patch]")
144+ }
145+
146 struct ServerImpl {
147 db: Connection,
148 }
149 @@ -60,6 +62,7 @@ impl Server for ServerImpl {
150 first.set_timestamp(post.0.timestamp as i64);
151 if let Some(subject) = envelope.subject {
152 first.set_subject(subject.as_str().into());
153+ first.set_is_patch(is_patch(&subject))
154 }
155 let message = String::from_utf8(post.0.message.clone()).unwrap();
156 first.set_body(message.as_str().into());
157 @@ -102,6 +105,10 @@ impl Server for ServerImpl {
158 let message_body = String::from_utf8(first_post.0.message).unwrap();
159 first.set_body(message_body.as_str().into());
160 first.set_timestamp(first_post.0.timestamp as i64);
161+ if let Some(subject) = envelope.subject {
162+ first.set_subject(subject.as_str().into());
163+ first.set_is_patch(is_patch(subject.as_str()));
164+ }
165 for (i, reply) in replies.iter().enumerate() {
166 let mut next = threads.reborrow().get(i as u32 + 1);
167 let envelope = Envelope::from_bytes(&reply.1.message, None).unwrap();
168 @@ -111,7 +118,12 @@ impl Server for ServerImpl {
169 let message_body = String::from_utf8(reply.1.message.to_vec()).unwrap();
170 next.set_body(message_body.as_str().into());
171 let message_text = envelope.body_bytes(&reply.1.message).text();
172+ if let Some(subject) = envelope.subject {
173+ next.set_subject(subject.as_str().into());
174+ next.set_is_patch(is_patch(subject.as_str()));
175+ }
176 next.set_text(message_text.as_str().into());
177+ next.set_timestamp(envelope.timestamp as i64);
178 }
179 Ok::<(), MailpotError>(())
180 };
181 @@ -145,10 +157,16 @@ impl Server for ServerImpl {
182 if let Some(from) = post.envelope_from.as_ref() {
183 message.set_from(from.as_str().into());
184 }
185+ let message_text = envelope.body_bytes(&post.message).text();
186 let message_body = String::from_utf8(post.message.to_vec()).unwrap();
187 message.set_body(message_body.as_str().into());
188- let message_text = envelope.body_bytes(&post.message).text();
189 message.set_text(message_text.as_str().into());
190+ message.set_timestamp(envelope.timestamp as i64);
191+ if let Some(subject) = envelope.subject {
192+ message.set_subject(subject.as_str().into());
193+ message.set_is_patch(is_patch(subject.as_str()));
194+ }
195+
196 Ok::<(), MailpotError>(())
197 };
198 match read_post(results) {
199 diff --git a/contrib/systemd/system/ayllu-mail.service b/contrib/systemd/system/ayllu-mail.service
200new file mode 100644
201index 0000000..cdd4afd
202--- /dev/null
203+++ b/contrib/systemd/system/ayllu-mail.service
204 @@ -0,0 +1,10 @@
205+ [Unit]
206+ Description=Ayllu Hyper Performant Code Forge (Mail Server Plugin)
207+
208+ [Service]
209+ ExecStart=/usr/bin/ayllu-mail serve
210+ User=ayllu
211+ Group=ayllu
212+
213+ [Install]
214+ WantedBy=multi-user.target
215 diff --git a/crates/api/v1/mail.capnp b/crates/api/v1/mail.capnp
216index eb951e7..b15c8df 100644
217--- a/crates/api/v1/mail.capnp
218+++ b/crates/api/v1/mail.capnp
219 @@ -18,6 +18,8 @@ struct Message {
220 body @6 :Text;
221 # text of just the email message
222 text @7 :Text;
223+ # true if the message is a patch
224+ isPatch @8 :Bool;
225 }
226
227 struct Thread {
228 @@ -25,6 +27,8 @@ struct Thread {
229 first @0 :Message;
230 # number of follow up messages associated with thread
231 nReplies @1 :Int64;
232+ # true if the thread contains one or more patch
233+ hasPatch @2 :Bool;
234 }
235
236 interface Server {
237 diff --git a/src/web2/routes/mail.rs b/src/web2/routes/mail.rs
238index e08efa4..c4b3c69 100644
239--- a/src/web2/routes/mail.rs
240+++ b/src/web2/routes/mail.rs
241 @@ -6,7 +6,9 @@ use axum::{
242 use serde::{Deserialize, Serialize};
243
244 use crate::config::Config;
245+ use crate::languages::Hint;
246 use crate::web2::error::Error;
247+ use crate::web2::highlight::Highlighter;
248 use crate::web2::middleware::rpc_initiator::{Initiator, Kind as InitiatorKind};
249 use crate::web2::middleware::template::Template;
250 use crate::web2::util::navigation;
251 @@ -33,6 +35,7 @@ struct Thread {
252 struct Message {
253 pub id: String,
254 pub message_id: String,
255+ pub subject: String,
256 pub created_at: i64,
257 pub from_address: String,
258 pub body: String,
259 @@ -105,6 +108,7 @@ pub async fn threads(
260 pub async fn thread(
261 Path(params): Path<Params>,
262 Extension(initiator): Extension<Initiator>,
263+ Extension(highlighter): Extension<Highlighter>,
264 Extension(cfg): Extension<Config>,
265 Extension((templates, mut ctx)): Extension<Template>,
266 ) -> Result<Html<String>, Error> {
267 @@ -126,23 +130,34 @@ pub async fn thread(
268 .set_message_id(params.thread_id.unwrap().as_str().into());
269 let result = req.send().promise.await?;
270 for message in result.get()?.get_thread()? {
271+ let text = message.get_text().unwrap().to_string().unwrap();
272+ let text = if message.get_is_patch() {
273+ let (_, diff) =
274+ highlighter.highlight(&text, None, None, Some(Hint::from("DIFF")), false);
275+ diff
276+ } else {
277+ text
278+ };
279 messages.push(Message {
280 id: message.get_id().to_string(),
281+ subject: message.get_subject()?.to_string().unwrap(),
282 message_id: message.get_message_id()?.to_string().unwrap(),
283 created_at: message.get_timestamp(),
284 from_address: message.get_address()?.to_string().unwrap(),
285 body: message.get_body()?.to_string().unwrap(),
286- text: message.get_text()?.to_string().unwrap(),
287+ text,
288 })
289 }
290 Ok(messages)
291 })
292 .await?;
293+ let subject = messages.first().map(|message| message.subject.clone());
294 ctx.insert("title", &format!("list {}", list.address));
295 ctx.insert("nav_elements", &navigation::global("mail", true));
296 ctx.insert("list", list);
297 ctx.insert("list_id", &list.id);
298 ctx.insert("messages", &messages);
299+ ctx.insert("subject", &subject);
300 let body = templates.render("thread.html", &ctx)?;
301 Ok(Html(body))
302 }
303 @@ -150,6 +165,7 @@ pub async fn thread(
304 pub async fn message(
305 Path(params): Path<Params>,
306 Extension(initiator): Extension<Initiator>,
307+ Extension(highlighter): Extension<Highlighter>,
308 Extension(cfg): Extension<Config>,
309 Extension((templates, mut ctx)): Extension<Template>,
310 ) -> Result<Html<String>, Error> {
311 @@ -170,12 +186,21 @@ pub async fn message(
312 .set_message_id(params.message_id.unwrap().as_str().into());
313 let result = req.send().promise.await?;
314 let message = result.get()?;
315+ let text = message.get_text().unwrap().to_string().unwrap();
316+ let text = if message.get_is_patch() {
317+ let (_, diff) =
318+ highlighter.highlight(&text, None, None, Some(Hint::from("DIFF")), false);
319+ diff
320+ } else {
321+ text
322+ };
323 Ok(Message {
324 id: message.get_id().to_string(),
325+ subject: message.get_subject()?.to_string().unwrap(),
326 message_id: message.get_message_id()?.to_string().unwrap(),
327 created_at: message.get_timestamp(),
328 body: message.get_body()?.to_string().unwrap(),
329- text: message.get_text()?.to_string().unwrap(),
330+ text,
331 from_address: message.get_address()?.to_string().unwrap(),
332 })
333 })
334 diff --git a/themes/default/base.scss b/themes/default/base.scss
335index d51bdd2..a0f4cb4 100644
336--- a/themes/default/base.scss
337+++ b/themes/default/base.scss
338 @@ -11,6 +11,8 @@
339 pre {
340 white-space: pre-wrap;
341 background-color: unset;
342+ color: unset;
343+ font-size: unset;
344 }
345
346 table {
347 diff --git a/themes/default/templates/post.html b/themes/default/templates/post.html
348index 8826000..e422cb0 100644
349--- a/themes/default/templates/post.html
350+++ b/themes/default/templates/post.html
351 @@ -4,11 +4,11 @@
352 <article>
353 <header>
354 <b>From: {{ message.from_address }}</b></br>
355- <b>To: ???</b></br>
356+ <b><a href="/mail/{{list_id}}/message/{{message.message_id}}">{{ message.message_id }}</a></b>
357 <b><a href="/discuss/mail/post/{{list_id}}/{{message.message_id}}">{{ message.message_id }}</a></b>
358 <span class="right">{{ message.created_at | format_epoch }}</span>
359 </header>
360- <pre>{{ message.text }}</pre>
361+ <pre>{{ message.text | safe }}</pre>
362 </article>
363 </section>
364 {% endblock %}
365 diff --git a/themes/default/templates/thread.html b/themes/default/templates/thread.html
366index d0005e8..33402dc 100644
367--- a/themes/default/templates/thread.html
368+++ b/themes/default/templates/thread.html
369 @@ -2,16 +2,20 @@
370 {% block content %}
371 <section class="thread-view">
372
373- {% for reply in messages %}
374 <article>
375 <header>
376- <b>From: {{ reply.from_address }}</b></br>
377- <b>To: ???</b></br>
378- <b><a href="/mail/{{list_id}}/message/{{reply.message_id}}">{{ reply.message_id }}</a></b>
379- <span class="right">{{ reply.created_at | format_epoch }}</span>
380+ <h1>{{ subject }}</h1>
381 </header>
382- <pre>{{ reply.text }}</pre>
383+ {% for reply in messages %}
384+ <article>
385+ <header>
386+ <b>From: {{ reply.from_address }}</b></br>
387+ <b><a href="/mail/{{list_id}}/message/{{reply.message_id}}">{{ reply.message_id }}</a></b>
388+ <span class="right">{{ reply.created_at | format_epoch }}</span>
389+ </header>
390+ <pre>{{ reply.text | safe }}</pre>
391+ </article>
392+ {% endfor %}
393+ </section>
394 </article>
395- {% endfor %}
396- </section>
397 {% endblock %}
398 diff --git a/www/content/docs/mail.md b/www/content/docs/mail.md
399new file mode 100644
400index 0000000..cf5dd97
401--- /dev/null
402+++ b/www/content/docs/mail.md
403 @@ -0,0 +1,10 @@
404+ +++
405+ title = "Mail"
406+ weight = 1
407+ +++
408+
409+ # Mailing List Support
410+
411+ Ayllu has full featured support for email based development workflows. It is
412+ based on the excellent [mailpot](https://git.meli-email.org/meli/mailpot)
413+ mailing list manager.
414 diff --git a/www/public/docs/architecture/index.html b/www/public/docs/architecture/index.html
415index b78cb30..25dbdfb 100644
416--- a/www/public/docs/architecture/index.html
417+++ b/www/public/docs/architecture/index.html
418 @@ -1 +1 @@
419- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li class=active><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a></ul></div><div class=doc-content><h1>Architecture</h1><p><strong>Ayllu is a new software project and it's design is evolving.</strong><p>It's basic architecture is that of a single binary providing a web interface to browse and interact with Git repositories as well as an RPC server based on <a href=https://capnproto.org/>Cap'n Proto</a> with an embedded client. The RPC server running in the core Ayllu binary is called the <code>job_server</code> and it provides an interface to interact with Ayllu for administrators. Much of the functionality of Ayllu is implemented via <code>RPC extensions</code> which are minimal binaries that are used to extend the core functionality of Ayllu.<p>The current architecture of Ayllu is depicted below:<p><a href=/assets/architecture.svg><img class=diagram src=/assets/architecture.svg></a></div></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
420\ No newline at end of file
421+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li class=active><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1>Architecture</h1><p><strong>Ayllu is a new software project and it's design is evolving.</strong><p>It's basic architecture is that of a single binary providing a web interface to browse and interact with Git repositories as well as an RPC server based on <a href=https://capnproto.org/>Cap'n Proto</a> with an embedded client. The RPC server running in the core Ayllu binary is called the <code>job_server</code> and it provides an interface to interact with Ayllu for administrators. Much of the functionality of Ayllu is implemented via <code>RPC extensions</code> which are minimal binaries that are used to extend the core functionality of Ayllu.<p>The current architecture of Ayllu is depicted below:<p><a href=/assets/architecture.svg><img class=diagram src=/assets/architecture.svg></a></div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
422\ No newline at end of file
423 diff --git a/www/public/docs/builds/index.html b/www/public/docs/builds/index.html
424index 50f1b4d..0b018c2 100644
425--- a/www/public/docs/builds/index.html
426+++ b/www/public/docs/builds/index.html
427 @@ -1,4 +1,4 @@
428- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li class=active><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a></ul></div><div class=doc-content><h1>Builds</h1><p>Ayllu contains a plugin called <code>ayllu-build</code> which is responsible for executing build manifests in a CI/CD environment. The design of the build system prioritizes the ability to run the entire workflow locally.<h3 id=an-example-local-workflow><a aria-label="Anchor link for: an-example-local-workflow" class=zola-anchor href=#an-example-local-workflow>An Example Local Workflow</a></h3><p>Build manifests are written in <a href=https://nickel-lang.org/>Nickel</a>.<pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh>mkdir -p my-test-repo/.ayllu/build
429+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li class=active><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1>Builds</h1><p>Ayllu contains a plugin called <code>ayllu-build</code> which is responsible for executing build manifests in a CI/CD environment. The design of the build system prioritizes the ability to run the entire workflow locally.<h3 id=an-example-local-workflow><a aria-label="Anchor link for: an-example-local-workflow" class=zola-anchor href=#an-example-local-workflow>An Example Local Workflow</a></h3><p>Build manifests are written in <a href=https://nickel-lang.org/>Nickel</a>.<pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh>mkdir -p my-test-repo/.ayllu/build
430 cd my-test-repo && git init
431 # create a simple workflow that prints "Hello" and "World"
432 cat <&LTEOF > .ayllu/build/main.ncl
433 @@ -34,4 +34,4 @@ ayllu_build plan
434 ayllu_build plan | dot -Tx11
435 # finally you can execute the workflow locally
436 ayllu_build evaluate
437- </code></pre></div></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
438\ No newline at end of file
439+ </code></pre></div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
440\ No newline at end of file
441 diff --git a/www/public/docs/configuration/index.html b/www/public/docs/configuration/index.html
442index cc3bb29..21d0927 100644
443--- a/www/public/docs/configuration/index.html
444+++ b/www/public/docs/configuration/index.html
445 @@ -1,4 +1,4 @@
446- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li class=active><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a></ul></div><div class=doc-content><h1>Configuration</h1><h1 id=initial-configuration><a aria-label="Anchor link for: initial-configuration" class=zola-anchor href=#initial-configuration>Initial Configuration</a></h1><p>After following the <a href=https://ayllu-forge.org/docs/installation>installation</a> you need to setup your configuration file and initialize the database.<h2 id=user-based-installation><a aria-label="Anchor link for: user-based-installation" class=zola-anchor href=#user-based-installation>User Based Installation</a></h2><pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh>mkdir ~/.config/ayllu
447+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li class=active><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1>Configuration</h1><h1 id=initial-configuration><a aria-label="Anchor link for: initial-configuration" class=zola-anchor href=#initial-configuration>Initial Configuration</a></h1><p>After following the <a href=https://ayllu-forge.org/docs/installation>installation</a> you need to setup your configuration file and initialize the database.<h2 id=user-based-installation><a aria-label="Anchor link for: user-based-installation" class=zola-anchor href=#user-based-installation>User Based Installation</a></h2><pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh>mkdir ~/.config/ayllu
448 ayllu config generate > ~/.config/ayllu/config.yaml
449 # open up config.yaml in your favorite editor and configure at least one
450 # collection
451 @@ -69,4 +69,4 @@ color = "#ff1493"
452 name = "go"
453 # Go is pink!
454 color = "#ff1493"
455- </code></pre></div></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
456\ No newline at end of file
457+ </code></pre></div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
458\ No newline at end of file
459 diff --git a/www/public/docs/developers/index.html b/www/public/docs/developers/index.html
460index 9b9ee14..15292cb 100644
461--- a/www/public/docs/developers/index.html
462+++ b/www/public/docs/developers/index.html
463 @@ -1,5 +1,5 @@
464- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li class=active><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a></ul></div><div class=doc-content><h1>Developers</h1><h1 id=developing-components><a aria-label="Anchor link for: developing-components" class=zola-anchor href=#developing-components>Developing Components</a></h1><p>Ayllu is split up into several distinct components, to work on one of them you typically want to start one of two feedback cycles: <code>lint->test->compile</code> or <code>compile->serve</code>. To start each one you can can run <code>scripts/test.sh $COMPONENT</code> or <code>scripts/watch.sh $COMPONENT</code> and the appropriate <code>cargo watch</code> command will be started for you.<h1 id=testing-the-entire-ci-workflow><a aria-label="Anchor link for: testing-the-entire-ci-workflow" class=zola-anchor href=#testing-the-entire-ci-workflow>Testing the Entire CI Workflow</a></h1><p>You can run all of the CI tests locally by invoking <code>ayllu-build</code> directly, assuming it is compiled it can be launched like this:<pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh># run all tests in .ayllu
465+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li class=active><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1>Developers</h1><h1 id=developing-components><a aria-label="Anchor link for: developing-components" class=zola-anchor href=#developing-components>Developing Components</a></h1><p>Ayllu is split up into several distinct components, to work on one of them you typically want to start one of two feedback cycles: <code>lint->test->compile</code> or <code>compile->serve</code>. To start each one you can can run <code>scripts/test.sh $COMPONENT</code> or <code>scripts/watch.sh $COMPONENT</code> and the appropriate <code>cargo watch</code> command will be started for you.<h1 id=testing-the-entire-ci-workflow><a aria-label="Anchor link for: testing-the-entire-ci-workflow" class=zola-anchor href=#testing-the-entire-ci-workflow>Testing the Entire CI Workflow</a></h1><p>You can run all of the CI tests locally by invoking <code>ayllu-build</code> directly, assuming it is compiled it can be launched like this:<pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh># run all tests in .ayllu
466 ayllu-build evaluate
467 </code></pre><h1 id=ayllu-forge-org><a aria-label="Anchor link for: ayllu-forge-org" class=zola-anchor href=#ayllu-forge-org>ayllu-forge.org</a></h1><p>The <a href=https://ayllu-forge.org>Ayllu website</a> and project documentation are built together with <a href=https://www.getzola.org/>Zola</a> which you must install. After which you can startup a local preview of the site with the following commands:<pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh>cd www && zola serve
468 </code></pre><p>The generated content are hosted directly from Ayllu and you simply need to build and commit the generated code directly into the repository.<pre class=language-sh data-lang=sh><code class=language-sh data-lang=sh>cd www && zola build
469- </code></pre><h2 id=diagrams><a aria-label="Anchor link for: diagrams" class=zola-anchor href=#diagrams>Diagrams</a></h2><p>Diagrams are built with <a href=https://www.nomnoml.com/>nomnoml</a> and their SVG content contain the source for generating the diagrams. Simply open one of the source SVGs up and copy-paste it to the editor of the nomnoml website.</div></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
470\ No newline at end of file
471+ </code></pre><h2 id=diagrams><a aria-label="Anchor link for: diagrams" class=zola-anchor href=#diagrams>Diagrams</a></h2><p>Diagrams are built with <a href=https://www.nomnoml.com/>nomnoml</a> and their SVG content contain the source for generating the diagrams. Simply open one of the source SVGs up and copy-paste it to the editor of the nomnoml website.</div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
472\ No newline at end of file
473 diff --git a/www/public/docs/faq/index.html b/www/public/docs/faq/index.html
474index 5634122..e5f1e73 100644
475--- a/www/public/docs/faq/index.html
476+++ b/www/public/docs/faq/index.html
477 @@ -1 +1 @@
478- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li class=active><a href=https://ayllu-forge.org/docs/faq/>FAQ</a></ul></div><div class=doc-content><h1>FAQ</h1><h5 id=what-does-ayllu-mean><a aria-label="Anchor link for: what-does-ayllu-mean" class=zola-anchor href=#what-does-ayllu-mean>What Does "Ayllu" Mean?</a></h5><p>The name <a href=https://en.wikipedia.org/wiki/Ayllu>Ayllu</a> <em>/ˈajʎu/</em>, <em>eye-joo</em> is the Quechua word for the traditional form of a community in the Andes region of South America, particularly in Bolivia and Peru.<h5 id=do-you-provide-hosting><a aria-label="Anchor link for: do-you-provide-hosting" class=zola-anchor href=#do-you-provide-hosting>Do You Provide Hosting?</a></h5><p>Not currently. If there was enough interest the project might offer hosted environments as a way to sustain it's development.</div></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
479\ No newline at end of file
480+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li class=active><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1>FAQ</h1><h5 id=what-does-ayllu-mean><a aria-label="Anchor link for: what-does-ayllu-mean" class=zola-anchor href=#what-does-ayllu-mean>What Does "Ayllu" Mean?</a></h5><p>The name <a href=https://en.wikipedia.org/wiki/Ayllu>Ayllu</a> <em>/ˈajʎu/</em>, <em>eye-joo</em> is the Quechua word for the traditional form of a community in the Andes region of South America, particularly in Bolivia and Peru.<h5 id=do-you-provide-hosting><a aria-label="Anchor link for: do-you-provide-hosting" class=zola-anchor href=#do-you-provide-hosting>Do You Provide Hosting?</a></h5><p>Not currently. If there was enough interest the project might offer hosted environments as a way to sustain it's development.</div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
481\ No newline at end of file
482 diff --git a/www/public/docs/index.html b/www/public/docs/index.html
483index fc836f8..f116940 100644
484--- a/www/public/docs/index.html
485+++ b/www/public/docs/index.html
486 @@ -1 +1 @@
487- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a></ul></div><div class=doc-content><h1 id=documentation><a aria-label="Anchor link for: documentation" class=zola-anchor href=#documentation>Documentation</a></h1><p>Welcome to the Ayllu documentation 📖, this is section serves as an authoritative reference on all things related to the Ayllu code forge!</div></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
488\ No newline at end of file
489+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1 id=documentation><a aria-label="Anchor link for: documentation" class=zola-anchor href=#documentation>Documentation</a></h1><p>Welcome to the Ayllu documentation 📖, this is section serves as an authoritative reference on all things related to the Ayllu code forge!</div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
490\ No newline at end of file
491 diff --git a/www/public/docs/installation/index.html b/www/public/docs/installation/index.html
492index c8c2665..c80ec60 100644
493--- a/www/public/docs/installation/index.html
494+++ b/www/public/docs/installation/index.html
495 @@ -1 +1 @@
496- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li class=active><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a></ul></div><div class=doc-content><h1>Installation</h1><h1 id=distribution-packages><a aria-label="Anchor link for: distribution-packages" class=zola-anchor href=#distribution-packages>Distribution Packages</a></h1><div class=warning>NOTE: Few distribution packages currently exist for Ayllu, any contributions in this regard would be gladly accepted!</div><h2 id=arch-linux><a aria-label="Anchor link for: arch-linux" class=zola-anchor href=#arch-linux>Arch Linux</a></h2><h6 id=release-package><a aria-label="Anchor link for: release-package" class=zola-anchor href=#release-package>Release Package</a></h6><p><a href=https://aur.archlinux.org/packages/ayllu>ayllu</a><h6 id=source-package><a aria-label="Anchor link for: source-package" class=zola-anchor href=#source-package>Source Package</a></h6><p><a href=https://aur.archlinux.org/packages/ayllu-git>ayllu-git</a><h1 id=from-source><a aria-label="Anchor link for: from-source" class=zola-anchor href=#from-source>From Source</a></h1><p>TODO</div></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
497\ No newline at end of file
498+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li class=active><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1>Installation</h1><h1 id=distribution-packages><a aria-label="Anchor link for: distribution-packages" class=zola-anchor href=#distribution-packages>Distribution Packages</a></h1><div class=warning>NOTE: Few distribution packages currently exist for Ayllu, any contributions in this regard would be gladly accepted!</div><h2 id=arch-linux><a aria-label="Anchor link for: arch-linux" class=zola-anchor href=#arch-linux>Arch Linux</a></h2><h6 id=release-package><a aria-label="Anchor link for: release-package" class=zola-anchor href=#release-package>Release Package</a></h6><p><a href=https://aur.archlinux.org/packages/ayllu>ayllu</a><h6 id=source-package><a aria-label="Anchor link for: source-package" class=zola-anchor href=#source-package>Source Package</a></h6><p><a href=https://aur.archlinux.org/packages/ayllu-git>ayllu-git</a><h1 id=from-source><a aria-label="Anchor link for: from-source" class=zola-anchor href=#from-source>From Source</a></h1><p>TODO</div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
499\ No newline at end of file
500 diff --git a/www/public/docs/mail/index.html b/www/public/docs/mail/index.html
501new file mode 100644
502index 0000000..b8afd24
503--- /dev/null
504+++ b/www/public/docs/mail/index.html
505 @@ -0,0 +1 @@
506+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><div class=documentation><div class=side-panel><ul><li><a href=https://ayllu-forge.org/docs/architecture/>Architecture</a><li><a href=https://ayllu-forge.org/docs/builds/>Builds</a><li><a href=https://ayllu-forge.org/docs/configuration/>Configuration</a><li><a href=https://ayllu-forge.org/docs/developers/>Developers</a><li><a href=https://ayllu-forge.org/docs/installation/>Installation</a><li><a href=https://ayllu-forge.org/docs/faq/>FAQ</a><li class=active><a href=https://ayllu-forge.org/docs/mail/>Mail</a></ul></div><div class=doc-content><h1>Mail</h1><h1 id=mailing-list-support><a aria-label="Anchor link for: mailing-list-support" class=zola-anchor href=#mailing-list-support>Mailing List Support</a></h1><p>Ayllu has full featured support for email based development workflows. It is based on the excellent <a href=https://git.meli-email.org/meli/mailpot>mailpot</a> mailing list manager.</div></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
507\ No newline at end of file
508 diff --git a/www/public/index.html b/www/public/index.html
509index be2f3d0..2b77472 100644
510--- a/www/public/index.html
511+++ b/www/public/index.html
512 @@ -1 +1 @@
513- <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><section class=home-header><div class=blurb><h1 id=hyper-performant-hackable-code-forge-built-on-open-standards>Hyper Performant & Hackable Code Forge Built on Open Standards</h1><p>Ayllu is a lightweight code forge designed to enable individuals and community projects to develop software in collaboration across open internet standards.</p><a href=https://ayllu-forge.org/projects/ayllu> <button>Source</button> </a></div><div class=screenshot><a href=https://ayllu-forge.org/projects/ayllu> <img class="screenshot night" src=/assets/images/ui.png></a><img class="screenshot day" src=/assets/images/ui-day.png></div></section><div class=home-wrapper><article><h4 id=general-purpose-git-ui>General Purpose Git UI</h4><p>General purpose web based UI for git. Browse hosted projects, view contributors, source code, blame, releases, etc.</article><article><h4 id=source-code-analysis>Source Code Analysis</h4><p>Super accurate syntax highlighting and code composition insight across project history.</article><article><h4 id=incremental-jobs>Incremental Jobs</h4><p>A built-in configurable incremental jobs system controlled via Git hooks and/or cron to extend forge functionality.</article><article><h4 id=extensible-plugin-system>Extensible Plugin System</h4><p>An extensible CapnProto based plugin system allows adding large external integrations via RPC calls.</article><article><h4 id=completely-themable>Completely Themable</h4><p>The web interface is fully customizable, a few themes <a href=https://ayllu-forge.org/config>already</a> exist and more are on the way.</article><article><h4 id=web-1-5>Web 1.5</h4><p>Super fast web frontend with first class support for RSS based project subscriptions. Ayllu loads faster than any other code forge in existence. <em>If it doesn't, it's a bug!</em></article><article><h4 id=static-hosting>Static Hosting</h4><p>Serve static websites directly from a git repository making project sites, documentation, or other assets simple to self-host.</article><article><h4 id=much-more>Much More</h4><p>New features planned such as continuous integration, mailing list support, external API, federation, and more. See the <strong>features</strong> tag in the <a href=https://ayllu-forge.org/projects/ayllu/bugs>bugs section</a>.</article></div></main><footer class=page-footer>2023, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
514\ No newline at end of file
515+ <!doctype html><html lang=en><head><meta charset=utf-8><link href=/main.css rel=stylesheet><link href=/assets/ayllu_logo.svg rel=icon type=image/svg+xml><link href=/assets/ayllu_logo.png rel=icon sizes=any type=image/png><title>Ayllu</title></head><nav><ul><li><a href=/> <img class=logo src=/assets/ayllu_logo.png> </a></ul><ul><li><a href=https://ayllu-forge.org/browse>browse</a><li><a href=/docs>docs</a></ul></nav><body class=container><div class=wrapper><main class=page-body><section class=home-header><div class=blurb><h1 id=hyper-performant-hackable-code-forge-built-on-open-standards>Hyper Performant & Hackable Code Forge Built on Open Standards</h1><p>Ayllu is a lightweight code forge designed to enable individuals and community projects to develop software in collaboration across open internet standards.</p><a href=https://ayllu-forge.org/projects/ayllu> <button>Source</button> </a></div><div class=screenshot><a href=https://ayllu-forge.org/projects/ayllu> <img class="screenshot night" src=/assets/images/ui.png></a><img class="screenshot day" src=/assets/images/ui-day.png></div></section><div class=home-wrapper><article><h4 id=general-purpose-git-ui>General Purpose Git UI</h4><p>General purpose web based UI for git. Browse hosted projects, view contributors, source code, blame, releases, etc.</article><article><h4 id=source-code-analysis>Source Code Analysis</h4><p>Super accurate syntax highlighting and code composition insight across project history.</article><article><h4 id=incremental-jobs>Incremental Jobs</h4><p>A built-in configurable incremental jobs system controlled via Git hooks and/or cron to extend forge functionality.</article><article><h4 id=extensible-plugin-system>Extensible Plugin System</h4><p>An extensible CapnProto based plugin system allows adding large external integrations via RPC calls.</article><article><h4 id=completely-themable>Completely Themable</h4><p>The web interface is fully customizable, a few themes <a href=https://ayllu-forge.org/config>already</a> exist and more are on the way.</article><article><h4 id=web-1-5>Web 1.5</h4><p>Super fast web frontend with first class support for RSS based project subscriptions. Ayllu loads faster than any other code forge in existence. <em>If it doesn't, it's a bug!</em></article><article><h4 id=static-hosting>Static Hosting</h4><p>Serve static websites directly from a git repository making project sites, documentation, or other assets simple to self-host.</article><article><h4 id=much-more>Much More</h4><p>New features planned such as continuous integration, mailing list support, external API, federation, and more. See the <strong>features</strong> tag in the <a href=https://ayllu-forge.org/projects/ayllu/bugs>bugs section</a>.</article></div></main><footer class=page-footer>2024, <a href=/projects/ayllu/blob/main/ATTRIBUTIONS.md>attributions</a></footer></div>
516\ No newline at end of file
517 diff --git a/www/public/sitemap.xml b/www/public/sitemap.xml
518index 9dedbdb..52aba1c 100644
519--- a/www/public/sitemap.xml
520+++ b/www/public/sitemap.xml
521 @@ -24,4 +24,7 @@
522 <url>
523 <loc>https://ayllu-forge.org/docs/installation/</loc>
524 </url>
525+ <url>
526+ <loc>https://ayllu-forge.org/docs/mail/</loc>
527+ </url>
528 </urlset>