Skip to content

Commit 05e78b6

Browse files
Resequenced docs pages and used color coding and subgraphs to make architecture graphs look really nice
1 parent 54f42a5 commit 05e78b6

File tree

7 files changed

+56
-38
lines changed

7 files changed

+56
-38
lines changed

_quarto.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ website:
1010
text: Home
1111
- href: docs/architecture.qmd
1212
text: Architecture
13-
- href: docs/installation.qmd
14-
text: Installation
1513
- href: docs/authentication.qmd
1614
text: Authentication
15+
- href: docs/installation.qmd
16+
text: Installation
1717
- href: docs/customization.qmd
1818
text: Customization
1919
- href: docs/deployment.qmd

docs/architecture.qmd

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,34 @@ This application uses a Post-Redirect-Get (PRG) pattern. The user submits a form
1212
from graphviz import Digraph
1313
1414
dot = Digraph()
15-
16-
dot.node('A', 'User submits form')
17-
dot.node('B', 'HTML/JS form validation')
18-
dot.node('C', 'Convert to Pydantic model')
19-
dot.node('D', 'Optional custom validation')
20-
dot.node('E', 'Update database')
21-
dot.node('F', 'Middleware error handler')
22-
dot.node('G', 'Render error template')
23-
dot.node('H', 'Redirect to GET endpoint')
24-
dot.node('I', 'Fetch updated data')
25-
dot.node('J', 'Re-render Jinja2 page template')
26-
15+
dot.attr(rankdir='TB')
16+
dot.attr('node', shape='box', style='rounded')
17+
18+
# Create client subgraph at top
19+
with dot.subgraph(name='cluster_client') as client:
20+
client.attr(label='Client')
21+
client.attr(rank='topmost')
22+
client.node('A', 'User submits form', fillcolor='lightblue', style='rounded,filled')
23+
client.node('B', 'HTML/JS form validation', fillcolor='lightblue', style='rounded,filled')
24+
25+
# Create server subgraph below
26+
with dot.subgraph(name='cluster_server') as server:
27+
server.attr(label='Server')
28+
server.node('C', 'Convert to Pydantic model', fillcolor='lightgreen', style='rounded,filled')
29+
server.node('D', 'Optional custom validation', fillcolor='lightgreen', style='rounded,filled')
30+
server.node('E', 'Update database', fillcolor='lightgreen', style='rounded,filled')
31+
server.node('F', 'Middleware error handler', fillcolor='lightgreen', style='rounded,filled')
32+
server.node('G', 'Render error template', fillcolor='lightgreen', style='rounded,filled')
33+
server.node('H', 'Redirect to GET endpoint', fillcolor='lightgreen', style='rounded,filled')
34+
server.node('I', 'Fetch updated data', fillcolor='lightgreen', style='rounded,filled')
35+
server.node('K', 'Re-render Jinja2 page template', fillcolor='lightgreen', style='rounded,filled')
36+
37+
with dot.subgraph(name='cluster_client_post') as client_post:
38+
client_post.attr(label='Client')
39+
client_post.attr(rank='bottommost')
40+
client_post.node('J', 'Display rendered page', fillcolor='lightblue', style='rounded,filled')
41+
42+
# Add visible edges
2743
dot.edge('A', 'B')
2844
dot.edge('B', 'A')
2945
dot.edge('B', 'C', label='POST Request to FastAPI endpoint')
@@ -33,12 +49,14 @@ dot.edge('D', 'E', label='Valid data')
3349
dot.edge('D', 'F', label='Custom Validation Error')
3450
dot.edge('E', 'H', label='Data updated')
3551
dot.edge('H', 'I')
36-
dot.edge('I', 'J')
52+
dot.edge('I', 'K')
53+
dot.edge('K', 'J', label='Return HTML')
3754
dot.edge('F', 'G')
55+
dot.edge('G', 'J', label='Return HTML')
3856
39-
dot.render('static/webapp_flow', format='png', cleanup=True)
57+
dot.render('static/data_flow', format='png', cleanup=True)
4058
```
4159

42-
![Data flow diagram](static/webapp_flow.png)
60+
![Data flow diagram](static/data_flow.png)
4361

4462
The advantage of the PRG pattern is that it is very straightforward to implement and keeps most of the rendering logic on the server side. The disadvantage is that it requires an extra round trip to the database to fetch the updated data, and re-rendering the entire page template may be less efficient than a partial page update on the client side.

docs/authentication.qmd

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,25 @@ auth.attr('node', shape='box', style='rounded')
4747
# Client-side nodes
4848
with auth.subgraph(name='cluster_client') as client:
4949
client.attr(label='Client')
50-
client.node('register_form', 'Submit registration')
51-
client.node('login_form', 'Submit login')
52-
client.node('store_cookies', 'Store secure cookies')
50+
client.node('register_form', 'Submit registration', fillcolor='lightblue', style='rounded,filled')
51+
client.node('login_form', 'Submit login', fillcolor='lightblue', style='rounded,filled')
52+
client.node('store_cookies', 'Store secure cookies', fillcolor='lightblue', style='rounded,filled')
5353
5454
# Server-side nodes
5555
with auth.subgraph(name='cluster_server') as server:
5656
server.attr(label='Server')
5757
# Registration path
58-
server.node('validate_register', 'Validate registration data')
59-
server.node('hash_new', 'Hash new password')
60-
server.node('store_user', 'Store user in database')
58+
server.node('validate_register', 'Validate registration data', fillcolor='lightgreen', style='rounded,filled')
59+
server.node('hash_new', 'Hash new password', fillcolor='lightgreen', style='rounded,filled')
60+
server.node('store_user', 'Store user in database', fillcolor='lightgreen', style='rounded,filled')
6161
6262
# Login path
63-
server.node('validate_login', 'Validate login data')
64-
server.node('verify_password', 'Verify password hash')
65-
server.node('fetch_user', 'Fetch user from database')
63+
server.node('validate_login', 'Validate login data', fillcolor='lightgreen', style='rounded,filled')
64+
server.node('verify_password', 'Verify password hash', fillcolor='lightgreen', style='rounded,filled')
65+
server.node('fetch_user', 'Fetch user from database', fillcolor='lightgreen', style='rounded,filled')
6666
6767
# Common path
68-
server.node('generate_tokens', 'Generate JWT tokens')
68+
server.node('generate_tokens', 'Generate JWT tokens', fillcolor='lightgreen', style='rounded,filled')
6969
7070
# Registration path
7171
auth.edge('register_form', 'validate_register', 'POST /register')
@@ -99,17 +99,17 @@ reset = Digraph(name='reset_flow')
9999
reset.attr(rankdir='TB')
100100
reset.attr('node', shape='box', style='rounded')
101101
102-
# Client-side nodes
103-
reset.node('forgot', 'User submits forgot password form')
104-
reset.node('reset', 'User submits reset password form')
105-
reset.node('email_client', 'User clicks reset link')
106-
107-
# Server-side nodes
108-
reset.node('validate', 'Validation')
109-
reset.node('token_gen', 'Generate reset token')
110-
reset.node('hash', 'Hash password')
111-
reset.node('email_server', 'Send email with Resend')
112-
reset.node('db', 'Database', shape='cylinder')
102+
# Client-side nodes - using light blue fill
103+
reset.node('forgot', 'User submits forgot password form', fillcolor='lightblue', style='rounded,filled')
104+
reset.node('reset', 'User submits reset password form', fillcolor='lightblue', style='rounded,filled')
105+
reset.node('email_client', 'User clicks reset link', fillcolor='lightblue', style='rounded,filled')
106+
107+
# Server-side nodes - using light green fill
108+
reset.node('validate', 'Validation', fillcolor='lightgreen', style='rounded,filled')
109+
reset.node('token_gen', 'Generate reset token', fillcolor='lightgreen', style='rounded,filled')
110+
reset.node('hash', 'Hash password', fillcolor='lightgreen', style='rounded,filled')
111+
reset.node('email_server', 'Send email with Resend', fillcolor='lightgreen', style='rounded,filled')
112+
reset.node('db', 'Database', shape='cylinder', fillcolor='lightgreen', style='filled')
113113
114114
# Add edges with labels
115115
reset.edge('forgot', 'token_gen', 'POST')

docs/static/auth_flow.png

2.43 KB
Loading

docs/static/data_flow.png

74.2 KB
Loading

docs/static/reset_flow.png

3.01 KB
Loading

docs/static/webapp_flow.png

-75.4 KB
Binary file not shown.

0 commit comments

Comments
 (0)