summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/launch.json6
-rw-r--r--Cargo.lock235
-rw-r--r--Cargo.toml23
-rw-r--r--src/handlers.rs16
-rw-r--r--src/main.rs9
-rw-r--r--src/posts/fs_post.rs4
-rw-r--r--src/tutors/fs_tutor.rs4
-rw-r--r--src/views.rs2
-rw-r--r--src/views/about.rs2
-rw-r--r--src/views/brochure.rs2
-rw-r--r--src/views/highered.rs6
-rw-r--r--src/views/index.rs2
-rw-r--r--src/views/k12.rs2
-rw-r--r--src/views/policies.rs2
-rw-r--r--src/views/post.rs2
-rw-r--r--src/views/posts.rs2
-rw-r--r--src/views/pro.rs6
-rw-r--r--static/brochure.css (renamed from templates/brochure/brochure.css)0
-rw-r--r--static/desktop.css33
-rw-r--r--static/linkchecker-out.sitemap.xml30
-rw-r--r--static/styles.css (renamed from templates/styles.css)130
-rw-r--r--templates/about/blurb.html3
-rw-r--r--templates/about/blurb.html.j23
-rw-r--r--templates/about/figure.html.j2 (renamed from templates/about/figure.html)0
-rw-r--r--templates/about/index.html.j2 (renamed from templates/about/index.html)10
-rw-r--r--templates/about/team.html11
-rw-r--r--templates/about/team.html.j211
-rw-r--r--templates/base.html.j2 (renamed from templates/base.html)34
-rw-r--r--templates/brochure/brochure.html.j2 (renamed from templates/brochure/brochure.html)14
-rw-r--r--templates/brochure/index.html.j2 (renamed from templates/brochure/index.html)12
-rw-r--r--templates/card.html14
-rw-r--r--templates/contact-buttons.html.j2 (renamed from templates/contact-buttons.html)0
-rw-r--r--templates/highered.html.j2173
-rw-r--r--templates/index.html130
-rw-r--r--templates/index.html.j2137
-rw-r--r--templates/k12.html.j2 (renamed from templates/k12.html)65
-rw-r--r--templates/policies.html.j2 (renamed from templates/policies.html)5
-rw-r--r--templates/post.html.j2 (renamed from templates/post.html)6
-rw-r--r--templates/posts.html15
-rw-r--r--templates/posts.html.j225
-rw-r--r--templates/pro.html.j280
-rw-r--r--templates/review.html.j221
42 files changed, 750 insertions, 537 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json
index d2d9ffe..74bf340 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -17,7 +17,11 @@
}
},
"args": [],
- "cwd": "${workspaceFolder}"
+ "cwd": "${workspaceFolder}",
+ "preLaunchTask": "rust: cargo build",
+ "env": {
+ "CT_BIND": "0.0.0.0:8001"
+ }
},
{
"type": "lldb",
diff --git a/Cargo.lock b/Cargo.lock
index d32f128..3852e23 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -28,69 +28,44 @@ dependencies = [
[[package]]
name = "askama"
-version = "0.12.1"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28"
+checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
dependencies = [
"askama_derive",
- "askama_escape",
- "comrak",
- "humansize",
- "num-traits",
+ "itoa",
"percent-encoding",
-]
-
-[[package]]
-name = "askama_axum"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a41603f7cdbf5ac4af60760f17253eb6adf6ec5b6f14a7ed830cf687d375f163"
-dependencies = [
- "askama",
- "axum-core",
- "http",
+ "serde",
+ "serde_json",
]
[[package]]
name = "askama_derive"
-version = "0.12.5"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83"
+checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
dependencies = [
"askama_parser",
"basic-toml",
- "mime",
- "mime_guess",
+ "memchr",
"proc-macro2",
"quote",
+ "rustc-hash",
"serde",
+ "serde_derive",
"syn",
]
[[package]]
-name = "askama_escape"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
-
-[[package]]
name = "askama_parser"
-version = "0.2.1"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0"
+checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
dependencies = [
- "nom",
-]
-
-[[package]]
-name = "async-trait"
-version = "0.1.88"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "memchr",
+ "serde",
+ "serde_derive",
+ "winnow",
]
[[package]]
@@ -101,13 +76,13 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "axum"
-version = "0.7.9"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
+checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5"
dependencies = [
- "async-trait",
"axum-core",
"bytes",
+ "form_urlencoded",
"futures-util",
"http",
"http-body",
@@ -135,13 +110,12 @@ dependencies = [
[[package]]
name = "axum-core"
-version = "0.4.5"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
+checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
dependencies = [
- "async-trait",
"bytes",
- "futures-util",
+ "futures-core",
"http",
"http-body",
"http-body-util",
@@ -198,12 +172,12 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "carpentertutoring"
-version = "0.1.0"
+version = "0.2.0"
dependencies = [
"askama",
- "askama_axum",
"axum",
"chrono",
+ "comrak",
"tokio",
"tower",
"tower-http",
@@ -212,6 +186,15 @@ dependencies = [
]
[[package]]
+name = "caseless"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8"
+dependencies = [
+ "unicode-normalization",
+]
+
+[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -219,23 +202,22 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.40"
+version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
+checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [
"num-traits",
]
[[package]]
name = "comrak"
-version = "0.18.0"
+version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "482aa5695bca086022be453c700a40c02893f1ba7098a2c88351de55341ae894"
+checksum = "d5c834ca54c5a20588b358f34d1533b4b498ddb5fd979cec6b22d0e8867a2449"
dependencies = [
+ "caseless",
"entities",
"memchr",
- "once_cell",
- "regex",
"slug",
"typed-arena",
"unicode_categories",
@@ -243,9 +225,9 @@ dependencies = [
[[package]]
name = "deunicode"
-version = "1.6.1"
+version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc55fe0d1f6c107595572ec8b107c0999bb1a2e0b75e37429a4fb0d6474a0e7d"
+checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04"
[[package]]
name = "entities"
@@ -366,15 +348,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
-name = "humansize"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
-dependencies = [
- "libm",
-]
-
-[[package]]
name = "hyper"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -428,22 +401,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
-name = "libm"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
-
-[[package]]
-name = "lock_api"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
-dependencies = [
- "autocfg",
- "scopeguard",
-]
-
-[[package]]
name = "log"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -460,9 +417,9 @@ dependencies = [
[[package]]
name = "matchit"
-version = "0.7.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
+checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "memchr"
@@ -487,12 +444,6 @@ dependencies = [
]
[[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
name = "miniz_oxide"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -513,16 +464,6 @@ dependencies = [
]
[[package]]
-name = "nom"
-version = "7.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
-dependencies = [
- "memchr",
- "minimal-lexical",
-]
-
-[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -563,29 +504,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
-name = "parking_lot"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
-dependencies = [
- "lock_api",
- "parking_lot_core",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
-dependencies = [
- "cfg-if",
- "libc",
- "redox_syscall",
- "smallvec",
- "windows-targets",
-]
-
-[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -622,15 +540,6 @@ dependencies = [
]
[[package]]
-name = "redox_syscall"
-version = "0.5.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -681,6 +590,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
+name = "rustc-hash"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+
+[[package]]
name = "rustversion"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -693,12 +608,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
-name = "scopeguard"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -762,15 +671,6 @@ dependencies = [
]
[[package]]
-name = "signal-hook-registry"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
-dependencies = [
- "libc",
-]
-
-[[package]]
name = "slug"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -824,18 +724,31 @@ dependencies = [
]
[[package]]
+name = "tinyvec"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
name = "tokio"
-version = "1.44.1"
+version = "1.45.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
+checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
- "parking_lot",
"pin-project-lite",
- "signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
@@ -999,6 +912,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
+name = "unicode-normalization"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
name = "unicode_categories"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1168,3 +1090,12 @@ name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "winnow"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec"
+dependencies = [
+ "memchr",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 30fd4f8..e7856fb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,17 +1,20 @@
[package]
name = "carpentertutoring"
-version = "0.1.0"
+version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-askama = { version = "0.12", features = ["markdown", "with-axum"], default-features = false }
-askama_axum = "0.4.0"
-axum = "0.7.5"
-chrono = { version = "0.4.38", default-features = false, features = ["now"] }
-tokio = { version = "1.40.0", features = ["full"] }
-tower = "0.5.0"
-tower-http = { version = "0.5.2", features = ["fs", "trace", "normalize-path"] }
-tracing = "0.1.40"
-tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
+askama = { version = "0.14" }
+axum = "0.8"
+chrono = { version = "0.4", default-features = false, features = ["now"] }
+comrak = { version = "0.39", default-features = false }
+tokio = { version = "1.45", default-features = false, features = [
+ "rt-multi-thread",
+ "macros",
+] }
+tower = "0.5"
+tower-http = { version = "0.5", features = ["fs", "trace", "normalize-path"] }
+tracing = "0.1"
+tracing-subscriber = { version = "0.3", features = ["env-filter"] }
diff --git a/src/handlers.rs b/src/handlers.rs
index 43d31fd..aa36e15 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -2,14 +2,16 @@ use crate::posts::abstractions::repo::PostRepo;
use crate::tutors::abstractions::tutor_repo::TutorRepo;
use crate::views::about::AboutView;
use crate::views::brochure::BrochureTemplate;
+use crate::views::highered::HigherEdTemplate;
use crate::views::index::IndexTemplate;
use crate::views::k12::K12Template;
use crate::views::policies::PoliciesTemplate;
use crate::views::post::PostView;
use crate::views::posts::PostsView;
+use crate::views::pro::ProTemplate;
use askama::Template;
use axum::extract::{Path, State};
-use axum::response::Html;
+use axum::response::{Html, Redirect};
use std::sync::Arc;
pub async fn about_handler(State(repo): State<Arc<impl TutorRepo>>) -> Html<String> {
@@ -42,6 +44,18 @@ pub async fn post_handler(
Html(view.render().unwrap())
}
+pub async fn post_redirect(Path(post_id): Path<String>) -> Redirect {
+ Redirect::permanent(&format!("/blog/{post_id}"))
+}
+
pub async fn k12_handler() -> Html<String> {
Html(K12Template {}.render().unwrap())
}
+
+pub async fn highered_handler() -> Html<String> {
+ Html(HigherEdTemplate {}.render().unwrap())
+}
+
+pub async fn pro_handler() -> Html<String> {
+ Html(ProTemplate {}.render().unwrap())
+}
diff --git a/src/main.rs b/src/main.rs
index 57b0256..a9cd722 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
+use axum::response::Redirect;
use axum::{extract::Request, routing::get, Router, ServiceExt};
use middleware::cache_control::cache_static;
use posts::fs_post_repo::FsPostRepo;
@@ -41,13 +42,17 @@ async fn main() {
info!("initializing router...");
let app = Router::new()
.route("/", get(handlers::index_handler))
- .route("/posts", get(handlers::posts_handler))
- .route("/posts/:post_id", get(handlers::post_handler))
+ .route("/posts", get(|| async { Redirect::permanent("/blog") }))
+ .route("/posts/{post_id}", get(handlers::post_redirect))
+ .route("/blog", get(handlers::posts_handler))
+ .route("/blog/{post_id}", get(handlers::post_handler))
.with_state(posts)
.route("/policies", get(handlers::policies_handler))
.route("/brochure", get(handlers::brochure_handler))
.route("/about", get(handlers::about_handler))
.route("/k12", get(handlers::k12_handler))
+ .route("/highered", get(handlers::highered_handler))
+ .route("/professional", get(handlers::pro_handler))
.with_state(tutors)
.nest_service("/assets", ServeDir::new(assets_dir))
.nest_service("/team", ServeDir::new(tutor_dir))
diff --git a/src/posts/fs_post.rs b/src/posts/fs_post.rs
index 4fc03b2..12ce538 100644
--- a/src/posts/fs_post.rs
+++ b/src/posts/fs_post.rs
@@ -1,3 +1,5 @@
+use comrak::Options;
+
use crate::posts::abstractions::post::Post;
use std::{borrow::Cow, fs, path::PathBuf};
@@ -19,7 +21,7 @@ impl Post for FsPost {
fn get_article(&self) -> Cow<str> {
let article = fs::read_to_string(&self.file).unwrap();
- Cow::Owned(article)
+ Cow::Owned(comrak::markdown_to_html(&article, &Options::default()))
}
fn get_description(&self) -> Cow<str> {
diff --git a/src/tutors/fs_tutor.rs b/src/tutors/fs_tutor.rs
index dc8a635..6b05fd8 100644
--- a/src/tutors/fs_tutor.rs
+++ b/src/tutors/fs_tutor.rs
@@ -1,3 +1,5 @@
+use comrak::Options;
+
use crate::tutors::abstractions::tutor::Tutor;
use std::{borrow::Cow, cmp::Ordering, fs, path::PathBuf};
@@ -25,7 +27,7 @@ impl Tutor for FsTutor {
let mut path = self.dir.to_owned();
path.push(format!("{}.md", self.get_id()));
let blurb = fs::read_to_string(path).unwrap();
- Cow::Owned(blurb)
+ Cow::Owned(comrak::markdown_to_html(&blurb, &Options::default()))
}
}
diff --git a/src/views.rs b/src/views.rs
index e9f1951..f880818 100644
--- a/src/views.rs
+++ b/src/views.rs
@@ -1,7 +1,9 @@
pub mod about;
pub mod brochure;
+pub mod highered;
pub mod index;
pub mod k12;
pub mod policies;
pub mod post;
pub mod posts;
+pub mod pro;
diff --git a/src/views/about.rs b/src/views/about.rs
index 349c9de..d2e0958 100644
--- a/src/views/about.rs
+++ b/src/views/about.rs
@@ -3,7 +3,7 @@ use crate::tutors::abstractions::tutor::Tutor;
use askama::Template;
#[derive(Template)]
-#[template(path = "about/index.html")]
+#[template(path = "about/index.html.j2")]
pub struct AboutView<T: Tutor> {
tutors: Vec<T>,
}
diff --git a/src/views/brochure.rs b/src/views/brochure.rs
index 0d2f8fc..fedf827 100644
--- a/src/views/brochure.rs
+++ b/src/views/brochure.rs
@@ -2,5 +2,5 @@ use crate::helpers::*;
use askama::Template;
#[derive(Template)]
-#[template(path = "brochure/index.html")]
+#[template(path = "brochure/index.html.j2")]
pub struct BrochureTemplate;
diff --git a/src/views/highered.rs b/src/views/highered.rs
new file mode 100644
index 0000000..108a76a
--- /dev/null
+++ b/src/views/highered.rs
@@ -0,0 +1,6 @@
+use crate::helpers::*;
+use askama::Template;
+
+#[derive(Template)]
+#[template(path = "highered.html.j2")]
+pub struct HigherEdTemplate;
diff --git a/src/views/index.rs b/src/views/index.rs
index 3ced24d..720749a 100644
--- a/src/views/index.rs
+++ b/src/views/index.rs
@@ -2,5 +2,5 @@ use crate::helpers::*;
use askama::Template;
#[derive(Template)]
-#[template(path = "index.html")]
+#[template(path = "index.html.j2")]
pub struct IndexTemplate;
diff --git a/src/views/k12.rs b/src/views/k12.rs
index eb9725f..c7dc019 100644
--- a/src/views/k12.rs
+++ b/src/views/k12.rs
@@ -2,5 +2,5 @@ use crate::helpers::*;
use askama::Template;
#[derive(Template)]
-#[template(path = "k12.html")]
+#[template(path = "k12.html.j2")]
pub struct K12Template;
diff --git a/src/views/policies.rs b/src/views/policies.rs
index 3d9787d..4253e6c 100644
--- a/src/views/policies.rs
+++ b/src/views/policies.rs
@@ -2,5 +2,5 @@ use crate::helpers::*;
use askama::Template;
#[derive(Template)]
-#[template(path = "policies.html")]
+#[template(path = "policies.html.j2")]
pub struct PoliciesTemplate;
diff --git a/src/views/post.rs b/src/views/post.rs
index 4f0554b..03e5ef2 100644
--- a/src/views/post.rs
+++ b/src/views/post.rs
@@ -3,7 +3,7 @@ use crate::posts::abstractions::post::Post;
use askama::Template;
#[derive(Template)]
-#[template(path = "post.html")]
+#[template(path = "post.html.j2")]
pub struct PostView<P: Post> {
post: P,
}
diff --git a/src/views/posts.rs b/src/views/posts.rs
index 82b5996..5091059 100644
--- a/src/views/posts.rs
+++ b/src/views/posts.rs
@@ -3,7 +3,7 @@ use crate::posts::abstractions::post::Post;
use askama::Template;
#[derive(Template)]
-#[template(path = "posts.html")]
+#[template(path = "posts.html.j2")]
pub struct PostsView<P: Post> {
posts: Vec<P>,
}
diff --git a/src/views/pro.rs b/src/views/pro.rs
new file mode 100644
index 0000000..eacfd7c
--- /dev/null
+++ b/src/views/pro.rs
@@ -0,0 +1,6 @@
+use crate::helpers::*;
+use askama::Template;
+
+#[derive(Template)]
+#[template(path = "pro.html.j2")]
+pub struct ProTemplate;
diff --git a/templates/brochure/brochure.css b/static/brochure.css
index 2abb118..2abb118 100644
--- a/templates/brochure/brochure.css
+++ b/static/brochure.css
diff --git a/static/desktop.css b/static/desktop.css
index 4d32d87..cdfcd34 100644
--- a/static/desktop.css
+++ b/static/desktop.css
@@ -1,6 +1,13 @@
@media only screen and (min-width: 700px) {
+ body {
+ font-size: 1.25em;
+ }
+
section {
- padding: 3em;
+ padding-top: 3em;
+ padding-bottom: 2em;
+ padding-left: 15em;
+ padding-right: 15em;
}
nav {
@@ -10,17 +17,8 @@
}
div.buttons {
- flex-direction: row-reverse;
- }
-
- form {
- margin-right: 10%;
- margin-left: 10%;
- }
-
- table td,
- table th {
- padding: 0.5em;
+ flex-direction: row;
+ justify-content: center;
}
section.flexible {
@@ -40,10 +38,6 @@
flex-grow: 1;
}
- .signature img {
- width: 30%;
- }
-
.logo img {
width: 15%;
display: block;
@@ -52,10 +46,11 @@
}
.card {
- padding: 2em;
+ padding: 1em;
}
- .modal .card {
- width: 25%;
+ section.cards {
+ margin-left: 25%;
+ margin-right: 25%;
}
} \ No newline at end of file
diff --git a/static/linkchecker-out.sitemap.xml b/static/linkchecker-out.sitemap.xml
index 3a96ca8..adafa42 100644
--- a/static/linkchecker-out.sitemap.xml
+++ b/static/linkchecker-out.sitemap.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- created by LinkChecker at 2025-05-09 20:14:26-004 -->
+<!-- created by LinkChecker at 2025-06-04 22:23:17-004 -->
<!-- Read the documentation at https://linkchecker.github.io/linkchecker/ -->
<!-- Write comments and bugs to https://github.com/linkchecker/linkchecker/issues -->
@@ -15,7 +15,17 @@
<priority>0.50</priority>
</url>
<url>
- <loc>https://carpentertutoring.com/posts</loc>
+ <loc>https://carpentertutoring.com/highered</loc>
+ <changefreq>daily</changefreq>
+ <priority>0.50</priority>
+ </url>
+ <url>
+ <loc>https://carpentertutoring.com/professional</loc>
+ <changefreq>daily</changefreq>
+ <priority>0.50</priority>
+ </url>
+ <url>
+ <loc>https://carpentertutoring.com/blog</loc>
<changefreq>daily</changefreq>
<priority>0.50</priority>
</url>
@@ -25,6 +35,11 @@
<priority>0.50</priority>
</url>
<url>
+ <loc>https://carpentertutoring.com/k12</loc>
+ <changefreq>daily</changefreq>
+ <priority>0.50</priority>
+ </url>
+ <url>
<loc>https://carpentertutoring.com/policies</loc>
<changefreq>daily</changefreq>
<priority>0.50</priority>
@@ -35,14 +50,19 @@
<priority>0.50</priority>
</url>
<url>
- <loc>https://carpentertutoring.com/posts/How%20to%20Use%20AI%20in%20College--and%20What%20NOT%20to%20Do</loc>
+ <loc>https://carpentertutoring.com/blog/Life%20After%20Graduation%3A%20Finding%20Meaning%20Beyond%20Grades</loc>
+ <changefreq>daily</changefreq>
+ <priority>0.50</priority>
+ </url>
+ <url>
+ <loc>https://carpentertutoring.com/blog/How%20to%20Use%20AI%20in%20College--and%20What%20NOT%20to%20Do</loc>
<changefreq>daily</changefreq>
<priority>0.50</priority>
</url>
<url>
- <loc>https://carpentertutoring.com/posts/Why%20We%20Procrastinate,%20and%20What%20We%20Can%20Do%20About%20It</loc>
+ <loc>https://carpentertutoring.com/blog/Why%20We%20Procrastinate,%20and%20What%20We%20Can%20Do%20About%20It</loc>
<changefreq>daily</changefreq>
<priority>0.50</priority>
</url>
</urlset>
-<!-- Stopped checking at 2025-05-09 20:14:39-004 (13 seconds) -->
+<!-- Stopped checking at 2025-06-04 22:23:29-004 (11 seconds) -->
diff --git a/templates/styles.css b/static/styles.css
index 609a0f7..5fcdfe9 100644
--- a/templates/styles.css
+++ b/static/styles.css
@@ -23,6 +23,7 @@ body {
body {
background-image: url("/assets/bg.webp");
+ background-size: 9em;
}
nav {
@@ -31,6 +32,7 @@ nav {
background-color: white;
position: fixed;
width: 100%;
+ z-index: 1;
}
nav img {
@@ -94,27 +96,12 @@ section {
section.banner {
text-align: center;
- padding-left: 0em;
- padding-right: 0em;
- margin-bottom: 0;
- background: linear-gradient(to right,
- rgba(255, 255, 255, 0) 0%,
- rgba(255, 255, 255, 1) 75%);
-}
-
-section.banner h1 {
- background: white;
- margin-top: 0;
- padding-top: 1em;
-}
-
-section.cards {
- background-color: transparent;
-}
-
-section.squarshed {
+ justify-content: center;
+ align-items: center;
+ gap: 1em;
padding-bottom: 1em;
- padding-top: 1em;
+ margin-bottom: 0;
+ background: linear-gradient(white 90%, rgba(255, 255, 255, 0));
}
.button img {
@@ -169,15 +156,6 @@ section a {
text-decoration: underline;
}
-.card {
- background-color: white;
- padding: 1em;
- border-radius: 1em;
- margin-left: 0;
- margin-right: 0;
- align-content: center;
-}
-
form input,
form textarea {
font-family: "PT Sans", sans-serif;
@@ -197,34 +175,6 @@ textarea {
resize: none;
}
-/* honeypot */
-textarea#beehive {
- display: none;
-}
-
-table {
- width: 100%;
- border-collapse: collapse;
-}
-
-table caption {
- text-align: left;
-}
-
-table th {
- text-align: right;
- color: var(--darkteal);
-}
-
-table td,
-table th {
- vertical-align: bottom;
-}
-
-tr:nth-child(even) {
- background-color: lightgray;
-}
-
picture img {
width: 100%;
}
@@ -244,20 +194,8 @@ section.flexible {
flex-direction: column;
}
-#reviews .card,
-#offerings .card {
- margin-left: 1em;
- margin-right: 1em;
- margin-top: 0.5em;
- margin-bottom: 0.5em;
- padding: 0.3em;
- flex: 1 0 21%;
- align-items: center;
- text-align: center;
-}
-
-#reviews,
-#offerings {
+section.cards {
+ background-color: transparent;
padding-left: 0;
padding-right: 0;
display: flex;
@@ -265,45 +203,33 @@ section.flexible {
justify-content: center;
}
-#offerings .full {
- flex: 1 1 100%;
-}
-
-.modal {
- position: fixed;
- z-index: 1;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
+.card {
+ align-content: center;
background-color: white;
- background-color: rgba(1, 1, 1, 0.4);
- overflow: auto;
- display: none;
- font-size: 1.5em;
-}
-
-.modal .card {
- max-height: 90%;
- max-width: 60%;
-}
-
-.modal a,
-.card a.button {
- float: right;
+ border-radius: 1em;
+ margin-bottom: 0.5em;
+ margin-left: 1em;
+ margin-right: 1em;
+ margin-top: 0.5em;
+ padding: 0.3em;
+ text-align: center;
}
-:target.modal {
- display: flex;
- justify-content: center;
- align-items: center;
+section#offerings .card {
+ flex: 1 0 21%;
}
-:target.modal .card {
- overflow: auto;
+section#offerings .full {
+ flex: 1 1 100%;
}
.centered {
text-align: center;
justify-content: center;
+}
+
+a[target*="_blank"]:after {
+ content: url('/assets/icons/open-in-new.svg');
+ display: inline-block;
+ width: 1em;
} \ No newline at end of file
diff --git a/templates/about/blurb.html b/templates/about/blurb.html
deleted file mode 100644
index 4389d47..0000000
--- a/templates/about/blurb.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div id="{{ tutor.get_id() }}">
- {{ tutor.get_blurb()|markdown }}
-</div>
diff --git a/templates/about/blurb.html.j2 b/templates/about/blurb.html.j2
new file mode 100644
index 0000000..a5e91d3
--- /dev/null
+++ b/templates/about/blurb.html.j2
@@ -0,0 +1,3 @@
+<div id="{{ tutor.get_id() }}">
+ {{ tutor.get_blurb() | safe }}
+</div> \ No newline at end of file
diff --git a/templates/about/figure.html b/templates/about/figure.html.j2
index 168aa4e..168aa4e 100644
--- a/templates/about/figure.html
+++ b/templates/about/figure.html.j2
diff --git a/templates/about/index.html b/templates/about/index.html.j2
index fcbc286..ad4480c 100644
--- a/templates/about/index.html
+++ b/templates/about/index.html.j2
@@ -1,20 +1,18 @@
-{% extends "base.html" %}
+{% extends "base.html.j2" %}
{% block main %}
<section class="banner">
<h1>About Us</h1>
</section>
-<section class=" squarshed">
- <p>
+<section>
<h2 style="font-size: 1.5em; text-align: center;">
There are many pathways to success. I started Carpenter Tutoring for
those seeking a little help finding their way.
</h2>
- </p>
</section>
-<section class=" flexible squarshed">
+<section class="flexible">
<figure class="shadowy">
<picture>
<source srcset="/assets/amy.webp" type="image/webp" />
@@ -64,6 +62,6 @@
</section>
-{% include "team.html" %}
+{% include "team.html.j2" %}
{% endblock %} \ No newline at end of file
diff --git a/templates/about/team.html b/templates/about/team.html
deleted file mode 100644
index c2b4498..0000000
--- a/templates/about/team.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% for tutor in tutors %}
-<sectionclass=" flexible">
- {% if loop.index0 % 2 == 0 %}
- {% include "blurb.html" %}
- {% include "figure.html" %}
- {% else %}
- {% include "figure.html" %}
- {% include "blurb.html" %}
- {% endif %}
- </section>
- {% endfor %} \ No newline at end of file
diff --git a/templates/about/team.html.j2 b/templates/about/team.html.j2
new file mode 100644
index 0000000..07637c8
--- /dev/null
+++ b/templates/about/team.html.j2
@@ -0,0 +1,11 @@
+{% for tutor in tutors %}
+<section class="flexible">
+ {% if loop.index0 % 2 == 0 %}
+ {% include "blurb.html.j2" %}
+ {% include "figure.html.j2" %}
+ {% else %}
+ {% include "figure.html.j2" %}
+ {% include "blurb.html.j2" %}
+ {% endif %}
+</section>
+{% endfor %} \ No newline at end of file
diff --git a/templates/base.html b/templates/base.html.j2
index 49d8c40..7029e18 100644
--- a/templates/base.html
+++ b/templates/base.html.j2
@@ -7,11 +7,9 @@
Tutoring Excellence Online and in Suffolk, VA - Carpenter Tutoring, LLC
{% endblock %}
</title>
- <style>
- {% block style %}
- {% include "styles.css" %}
- {% endblock %}
- </style>
+ {% block styles %}
+ <link rel="stylesheet" href="/styles.css" />
+ {% endblock %}
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link rel="stylesheet" href="/desktop.css" />
<link rel="stylesheet" href="/widescreen.css" />
@@ -33,11 +31,11 @@
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-RZLJ3ZBKZL"></script>
<script>
- window.dataLayer = window.dataLayer || [];
- function gtag(){dataLayer.push(arguments);}
- gtag('js', new Date());
+ window.dataLayer = window.dataLayer || [];
+ function gtag() { dataLayer.push(arguments); }
+ gtag('js', new Date());
- gtag('config', 'G-RZLJ3ZBKZL');
+ gtag('config', 'G-RZLJ3ZBKZL');
</script>
@@ -47,13 +45,11 @@
<a href="/k12">K-12</a>
<a href="/highered">Higher Ed</a>
<a href="/professional">Pros</a>
- <a href="/posts">Posts</a>
+ <a href="/blog">Blog</a>
<a href="/brochure">Brochure</a>
- <a href="/#help">Helpful Links</a>
<a href="/policies">Policies</a>
<a href="/about">Team</a>
- <a href="/#reviews">Reviews</a>
- <a href="/#contact">Contact</a>
+ <a href="#contact">Contact</a>
<a>More&hellip;</a>
</nav>
@@ -66,16 +62,16 @@
<picture>
<source srcset="/assets/logo.webp" type="image/webp" />
<source srcset="/assets/logo.png" type="image/png" />
- <img alt="logo" src="/assets/logo.png" />
+ <img alt="Carpenter Tutoring logo" src="/assets/logo.png" />
</picture>
</figure>
<div id="contact" class="buttons centered">
- {% include "contact-buttons.html" %}
+ {% include "contact-buttons.html.j2" %}
</div>
<p>
- &copy; 2019-{{ self::current_year() }} Carpenter Tutoring, LLC. All rights reserved.
+ &copy; 2019-{{ self::current_year() }} Carpenter Tutoring, LLC. All rights reserved.
</p>
<p>
<a href="https://g.page/carpenter-tutoring?share">Visit me on Google</a>
@@ -89,7 +85,9 @@
</footer>
<script src="/nav.js"></script>
- <link href="https://fonts.googleapis.com/css2?family=Architects+Daughter&family=Indie+Flower&family=PT+Sans&display=swap" rel="stylesheet" />
+ <link
+ href="https://fonts.googleapis.com/css2?family=Architects+Daughter&family=Indie+Flower&family=PT+Sans&display=swap"
+ rel="stylesheet" />
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/templates/brochure/brochure.html b/templates/brochure/brochure.html.j2
index b5a3cd3..9ff3d46 100644
--- a/templates/brochure/brochure.html
+++ b/templates/brochure/brochure.html.j2
@@ -12,26 +12,26 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
<div class="paper">
<div class="page left">
<div class="side front">
- <img src="/assets/brochure/brochure-front-left.png"/>
+ <img src="/assets/brochure/brochure-front-left.png" alt="brochure front left page" />
</div>
<div class="side back">
- <img src="/assets/brochure/brochure-back-left.png"/>
+ <img src="/assets/brochure/brochure-back-left.png" alt="brochure back left page" />
</div>
</div>
<div class="page right">
<div class="side front">
- <img src="/assets/brochure/brochure-front-right.png"/>
+ <img src="/assets/brochure/brochure-front-right.png" alt="brochure front right page" />
</div>
<div class="side back">
- <img src="/assets/brochure/brochure-back-right.png"/>
+ <img src="/assets/brochure/brochure-back-right.png" alt="brochure back right page" />
</div>
</div>
<div class="page center">
<div class="side front">
- <img src="/assets/brochure/brochure-front-center.png"/>
+ <img src="/assets/brochure/brochure-front-center.png" alt="brochure front center page" />
</div>
<div class="side back">
- <img src="/assets/brochure/brochure-back-center.png"/>
+ <img src="/assets/brochure/brochure-back-center.png" alt="brochure back center page" />
</div>
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/templates/brochure/index.html b/templates/brochure/index.html.j2
index 6304887..a3a5b33 100644
--- a/templates/brochure/index.html
+++ b/templates/brochure/index.html.j2
@@ -1,8 +1,8 @@
-{% extends "base.html" %}
+{% extends "base.html.j2" %}
-{% block style %}
-{% include "../styles.css" %}
-{% include "brochure.css" %}
+{% block styles %}
+<link rel="stylesheet" href="/styles.css" />
+<link rel="stylesheet" href="/brochure.css" />
{% endblock %}
{% block main %}
@@ -21,12 +21,10 @@
desktop screen.
</p>
- {% include "brochure.html" %}
+ {% include "brochure.html.j2" %}
</section>
-<section></section>
-
<script>
{% include "brochure.js" %}
</script>
diff --git a/templates/card.html b/templates/card.html
deleted file mode 100644
index 1397bc8..0000000
--- a/templates/card.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<div class="card">
- <h2>
- {% block title %}
- Card Title
- {% endblock %}
- </h2>
-
- <p>
- {% block content %}
- Stuff in the card
- {% endblock %}
- </p>
-
-</div> \ No newline at end of file
diff --git a/templates/contact-buttons.html b/templates/contact-buttons.html.j2
index bae7460..bae7460 100644
--- a/templates/contact-buttons.html
+++ b/templates/contact-buttons.html.j2
diff --git a/templates/highered.html.j2 b/templates/highered.html.j2
new file mode 100644
index 0000000..c1d5f09
--- /dev/null
+++ b/templates/highered.html.j2
@@ -0,0 +1,173 @@
+{% extends "base.html.j2" %}
+
+{% block main %}
+
+<section class="banner flexible">
+ <h1>Higher Education Services</h1>
+ <h6>Personalized partnership and support from a higher education expert.</h6>
+</section>
+
+<section id="offerings" class="cards">
+ <div class="card full">
+ <h3>
+ Higher Education Services
+ </h3>
+ </div>
+
+ <div class="card">
+ <p> <a href="#offering-academic-coaching"> Academic Coaching </a> </p>
+ </div>
+
+ <div class="card">
+ <p> <a href="#offering-application-essay-consulting">Application Essay Consulting</a> </p>
+ </div>
+
+ <div class="card">
+ <p><a href="#offering-college-transition">College Transition</a></p>
+ </div>
+
+ <div class="card">
+ <p><a href="#offering-dissertation-thesis-coaching">Dissertation and Thesis Coaching</a></p>
+ </div>
+
+ <div class="card">
+ <p><a href="#offering-subject-tutoring">Subject Tutoring</a></p>
+ </div>
+
+ <div class="card">
+ <p><a href="#offering-writing-support">Writing Support</a></p>
+ </div>
+</section>
+
+<section id="offering-academic-coaching">
+ <h2>Academic Coaching</h2>
+
+ <p>
+ Academic Coaching teaches and models the skills students need for success through graduation and beyond. We work
+ together to create and execute realistic plans to handle the responsibilities of each week. Tailored to each
+ student's individual needs, Academic Coaching provides students with a partner in navigating both academic and
+ personal responsibilities with the goal of increasing confidence, autonomy, and self-sufficiency. Topics
+ covered include but are not limited to
+
+ <ul>
+ <li>Time and stress management</li>
+ <li>Task prioritization</li>
+ <li>Organization</li>
+ <li>Effective study techniques</li>
+ <li>Note-taking </li>
+ <li>Motivation</li>
+ <li>Overcoming procrastination</li>
+ <li>Self-advocacy </li>
+ <li>Communication </li>
+ <li>Understanding instructor expectations</li>
+ </ul>
+
+ </p>
+</section>
+
+<section id="offering-application-essay-consulting">
+ <h2>Application Essay Consulting</h2>
+
+ <p>
+ Whether your higher education journey is just beginning or you're applying for a terminal degree program, the
+ essay is an important part of any application. From picking a topic to telling your story to editing a final
+ draft, you have a dedicated and knowledgeable partner. Students remain in control during every stage of the
+ writing process with the added benefits of real-time feedback, guidance, and recommendations. Support for
+ supplemental essays is also available.
+ </p>
+</section>
+
+<section id="offering-college-transition">
+ <h2>College Transition</h2>
+
+ <p>
+ When I worked in higher education, I saw talented students struggle, often because they hadn't solidified the
+ skills
+ they'd need for success in college or hadn't had the opportunity to learn about the resources and services
+ available to them on campus. The College Transition offering provides students the toolkit of techniques and
+ tips they'll need and introduces relevant university services and resources. Whether you're entering your first
+ semester of higher education or seeking a new degree after attending to a family or career, you don't have to
+ navigate your adjustment to life in higher education alone.
+ </p>
+</section>
+
+<section id="offering-dissertation-thesis-coaching">
+ <h2>Dissertation and Thesis Coaching</h2>
+
+ <p>
+ Creating a large written work requires effective planning, and long-term effort can be difficult to maintain
+ without some help. Bring a partner into your process to help set and reach realistic goals, break through
+ barriers impeding your progress, strengthen your writing and analysis, and stay motivated. On-going coaching
+ relationships that address all stages of the research and writing process as well as editing services are
+ available.
+
+ </p>
+ <p>
+ Past thesis and dissertation client works encompass a wide variety of fields including education, heliophysics,
+ sociology, biostatistics, computer science, and marketing and branding pursued at institutions such as William &
+ Mary, Vanderbilt, University of Michigan, Harvard, and Yonsei University in South Korea.
+ </p>
+</section>
+
+<section id="offering-subject-tutoring">
+ <h2>Subject Tutoring</h2>
+
+ <p>
+ Support is available in understanding and practicing course content for the following subjects:
+
+ <ul>
+ <li>English Literature</li>
+ <li>Latin language</li>
+ <li>Math (dependent on tutor availability)</li>
+ <li>Computer Science (dependent on tutor availability)</li>
+ <li>Biology</li>
+ <li>Chemistry/Organic Chemistry</li>
+ <li>Life Sciences/Earth Science</li>
+ <li>Physiology/Anatomy</li>
+ </ul>
+
+ For support in preparing essays, final papers, presentations, discussion papers, and other communication-based
+ assignments in any subject, see <a href="#offering-writing-support">Writing Support</a>.
+ </p>
+
+ <p>
+ For support in making the most of class instruction, preparing for exams, and planning for the semester ahead in
+ any
+ subject, see <a href="#offering-academic-coaching">Academic Coaching</a>.
+ </p>
+</section>
+
+<section id="offering-writing-support">
+ <h2>Writing Support</h2>
+
+ <p>
+ Whether you've been assigned a brief discussion post or a 15-page research assignment, you've got a partner in
+ producing a meaningful and well-organized response. From brainstorming and conducting research to organizing and
+ editing your paper, tailored support is available at every stage of the writing process for all
+ communication-based course assignments. Additionally, receive support in setting and meeting realistic progress
+ goals, fully understanding assignment expectations, and adhering to assignment guidelines including those
+ pertaining to citations and references.
+ </p>
+</section>
+
+<section id="reviews" class="cards">
+ {% let name = "Marie R." %}
+ {% let title = "Dissertation Coaching client" %}
+ {% let quote = "I highly recommend Amy as a dissertation coach. Amy is a very kind and patient person. Over the time we worked together, she helped me take down the barriers that were preventing me from moving forward in my process and assisted me in creating a plan to get to the finish line and achieve my goal. She was very helpful with revising and editing my writing to strengthen it. She helped me think creatively, so I could clarify and expand upon my findings. Amy not only pointed out grammatical errors and typos, but she made sure I was able to keep my voice consistent in my writing. Because of her, I was able to finish my doctoral degree, something that I will be forever grateful to her for." %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Langston J." %}
+ {% let title = "Academic Coaching client" %}
+ {% let quote = "Amy is honestly a wonderful tutor. She helped me figure out how to work more effectively and ultimately improve my GPA in a way that worked for my specific needs at the time. She is also just an amazing person to work with and I really think anyone looking for a tutor would be in good hands here." %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Jamie J." %}
+ {% let title = "Dissertation Coaching client" %}
+ {% let quote = "I'm in the final stages of my biostatistics PhD, and enlisted Amy to help with editing and polishing my dissertation. She took the time to go through my entire dissertation and leave detailed feedback on every page (and there are so many of them)!!! The comments were all thoughtful and tailored specifically to my school's formatting and content requirements; she took the time to look them up without me even thinking to ask her to check against those. And she got through the entire thing in such a quick amount of time given how much material there is-I can go on and on!! I can't recommend Amy enough to anyone who needs tutoring or writing services, or if you have a dissertation that needs editing; not only is she incredibly detail-oriented and great at writing, she's also an absolute pleasure to work with!" %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+</section>
+
+{% endblock %} \ No newline at end of file
diff --git a/templates/index.html b/templates/index.html
deleted file mode 100644
index b5f4bd6..0000000
--- a/templates/index.html
+++ /dev/null
@@ -1,130 +0,0 @@
-{% extends "base.html" %}
-
-{% block main %}
-<!--banner-->
-<section class="banner">
- <!-- <section class="banner flexible"> -->
- <!-- <figure class="logo">
- <picture>
- <source srcset="/assets/logo.webp" type="image/webp" />
- <source srcset="/assets/logo.png" type="image/png" />
- <img alt="logo" src="/assets/logo.png" />
- </picture>
- </figure> -->
- <h1>CARPENTER TUTORING</h1>
-</section>
-
-<section class="centered">
- <h2>
- Building confidence on the way to content mastery.
- </h2>
-</section>
-
-<section id="offerings" class="cards">
- <div class="card full">
- <h3>
- Services
- </h3>
- </div>
-
- <div class="card">
- <p>
- <a href="/k12">
- K-12
- </a>
- </p>
- </div>
-
- <div class="card">
- <p>
- <a href="/highered">
- Higher Education
- </a>
- </p>
- </div>
-
- <div class="card">
- <p>
- <a href="/professional">
- Professional
- </a>
- </p>
- </div>
-</section>
-
-<!-- help -->
-<section class="squarshed centered" id="help">
- <h2>Helpful Links</h2>
- <a class="button primary centered" href="/brochure">View an interactive brochure of our offerings</a>
- <a class="button centered" href="/policies">See policies and procedures regarding scheduling, payment, and
- booking</a>
-</section>
-
-<!-- reviews -->
-<section id="reviews">
-
- <div class="card">
- <h2>C.L. Cannon</h2>
- <blockquote>
- I hired Amy to complete an end-of-the-year evaluation for both of my Elementary aged sons. This being
- our
- first year of independent home instruction, the task of testing and/or evaluation was daunting! Amy put
- my
- fears to rest! She was super easy to work with, had great communication skills, and answered all my
- questions in a timely and informative manner! I would highly recommend her services!
- </blockquote>
- <p>
- <a href="https://goo.gl/maps/kC4aTuFqpiyLCJ2r8">View on Google</a>
- or
- <a href="https://g.page/carpenter-tutoring/review?np">leave a review.</a>
- </p>
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- </div>
-
- <div class="card">
- <h2>Lee Crabtree</h2>
- <blockquote>
- Amy is a wonderful tutor who helped my child (who does not like help at all) though some difficult
- classes
- where the teacher was not providing the support my child needed. Highly recommended.
- </blockquote>
- <p>
- <a href="https://goo.gl/maps/73wWvyS7azkBBkA39">View on Google</a>
- or
- <a href="https://g.page/carpenter-tutoring/review?np">leave a review.</a>
- </p>
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- </div>
-
- <div class="card">
- <h2>Connor Fenton</h2>
- <blockquote>
- I was a Graduate student at the College of William and Mary who needed to pass a Latin Language test as
- part
- of my degree requirements. I was struggling with refreshing my Latin after a few years out of the
- classroom
- and Amy was both professional and helpful. With her tutoring I was able to pass my test and finish my
- degree. She is very considerate and easy to work with.
- </blockquote>
- <p>
- <a href="https://goo.gl/maps/73wWvyS7azkBBkA39">View on Google</a>
- or
- <a href="https://g.page/carpenter-tutoring/review?np">leave a review.</a>
- </p>
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- <img src="/assets/icons/star-box.svg" alt="star" />
- </div>
-
-</section>
-{% endblock %} \ No newline at end of file
diff --git a/templates/index.html.j2 b/templates/index.html.j2
new file mode 100644
index 0000000..d6d0a1a
--- /dev/null
+++ b/templates/index.html.j2
@@ -0,0 +1,137 @@
+{% extends "base.html.j2" %}
+
+{% block main %}
+<!--banner-->
+<section class="banner flexible">
+ <h1>
+ CARPENTER TUTORING
+ </h1>
+ <h6>
+ Discovering your path to success.
+ </h6>
+</section>
+
+<!-- offerings -->
+<section id="offerings" class="cards">
+ <div class="card full">
+ <h3>
+ Services
+ </h3>
+ </div>
+
+ <div class="card">
+ <p>
+ <a href="/k12">
+ K-12
+ </a>
+ </p>
+ </div>
+
+ <div class="card">
+ <p>
+ <a href="/highered">
+ Higher Education
+ </a>
+ </p>
+ </div>
+
+ <div class="card">
+ <p>
+ <a href="/professional">
+ Professional
+ </a>
+ </p>
+ </div>
+</section>
+
+<!-- help -->
+<section class="centered" id="help">
+ <h2>Helpful Links</h2>
+ <div class="buttons">
+ <a class="button primary centered" href="/brochure">View an interactive brochure of our offerings</a>
+ <a class="button centered" href="/policies">See policies and procedures regarding scheduling, payment, and
+ booking</a>
+ </div>
+</section>
+
+<!-- blurb -->
+<section id="blurb" class="flexible">
+ <div>
+ <h2>Our Philosophy &amp; Practice</h2>
+
+ <p>
+ Proudly assisting clients in our home region of Hampton Roads, VA and beyond, our private tutoring practice
+ serves students and professionals of all ages and stages through one-on-one appointments tailored to
+ individual
+ needs and goals.
+ </p>
+
+ <p>
+ Our approach is grounded in three core beliefs:
+
+ <ol>
+ <li>Everyone has their own path to success.</li>
+ <li>Building confidence is a vital step on the way to content mastery.</li>
+ <li>Taking the time to truly learn each person's preferences and ways of processing information is the
+ foundation of a meaningful tutoring, coaching, or mentoring relationship.</li>
+ </ol>
+
+ These beliefs guide every aspect of our work. We recognize, respect, and celebrate the individuality of each
+ person
+ we serve. By infusing compassion, understanding, and patience into every appointment and valuing client voices
+ when
+ setting focus areas, we meet clients where they are to build meaningful relationships that offer not only
+ instruction but encouragement.
+ </p>
+
+ <p>
+ Most services are offered by founder Amy Carpenter, M.Ed. A small team of experienced and caring tutors
+ assists
+ with additional subjects and specialties. We specialize in remote services, with limited in-person support
+ available in select locations.
+ </p>
+
+ <p>
+ We are ready and excited to serve you as you discover your path to success. <a href="#contact">Contact
+ us</a> today to begin your
+ journey.
+ </p>
+ </div>
+
+ <figure class="shadowy">
+ <picture>
+ <source srcset="/assets/amy-sunny.webp" type="image/webp" />
+ <source srcset="/assets/amy-sunny.png" type="image/png" />
+ <img alt="Amy Carpenter" src="/assets/amy-sunny.png" />
+ </picture>
+ <figcaption>Amy Carpenter, M.Ed.</figcaption>
+ </figure>
+</section>
+
+<!-- reviews -->
+<section id="reviews" class="cards">
+ {% let name = "Briana A." %}
+ {% let title = "K-12 Subject Tutoring parent" %}
+ {% let quote = "Amy Carpenter was an outstanding tutor for my 8th grader in Algebra I. She was patient, encouraging, organized, and very fairly priced for a one hour session from the comfort of our home (via zoom). I would rate her services at 10/10 and recommend her to anyone in need of tutoring services." %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Kristina W." %}
+ {% let title = "K-12 Subject Tutoring & Higher Education Academic Coaching parent" %}
+ {% let quote = "Amy Carpenter is an amazingly gifted tutor. She is kind, patient, potisiv[e], encouraging, and supportive. She treats all of her students with respect and never makes them feel \"lesser than\" or that their questions are \"stupid.\" She has made a huge difference to our lives and our family is very thankful for her expertise and support!" %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Karla R." %}
+ {% let title = "Higher Education Academic Coaching parent" %}
+ {% let quote = "Amy does a great job at keeping our son on task and ensuring that he does not miss any assignments or important deadlines. I value Amy’s level headedness the most in our interactions as I feel like I can accidentally slip into anxiety mode with my son when he has hiccups and Amy has been a great resource in helping me check my emotions as she calmly assures me that he [is] staying on track with his studies. Amy has also gone above and beyond by helping our son contemplate his next stage with regard to graduate school or entering the workforce which is definitely still a \"work in progress\". I can wholeheartedly recommend Amy and have already done so many times to friends and family." %}
+ {% let stars = 0 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Kim J." %}
+ {% let title = "K-12 Subject Tutoring parent" %}
+ {% let quote = "So glad we found Amy! I have seen my daughter's confidence and grades improve since Amy started tutoring her. She meets my daughter at her level and helps her grow. Can't say enough good things about her!" %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+</section>
+{% endblock %} \ No newline at end of file
diff --git a/templates/k12.html b/templates/k12.html.j2
index 6467d55..cd6fd6a 100644
--- a/templates/k12.html
+++ b/templates/k12.html.j2
@@ -1,13 +1,10 @@
-{% extends "base.html" %}
+{% extends "base.html.j2" %}
{% block main %}
-<section class="banner">
+<section class="banner flexible">
<h1>K-12 Services</h1>
-</section>
-
-<section>
- <h2>See your student thrive with personalized support.</h2>
+ <h6>See your student thrive with personalized support.</h6>
</section>
<section id="offerings" class="cards">
@@ -82,10 +79,10 @@
<li>Time and stress management</li>
<li>Task prioritization</li>
<li>Organization</li>
- <li>Effective studio techniques</li>
+ <li>Effective study techniques</li>
<li>Note-taking</li>
<li>Motivation</li>
- <li>Procrastination</li>
+ <li>Overcoming procrastination</li>
<li>Self-advocacy</li>
<li>Communication</li>
</ul>
@@ -112,7 +109,8 @@
</h2>
<p>
- When I worked at colleges, I saw talented students struggle, often because they hadn't solidified the skills
+ When I worked in higher education, I saw talented students struggle, often because they hadn't solidified the
+ skills
they'd need for success in college or hadn't had the opportunity to learn about the resources and services
available to them on campus. The College Transition offering provides students the toolkit of techniques and
tips they'll need and introduces relevant university services and resources <em>before</em> students arrive for
@@ -126,7 +124,7 @@
</h2>
<p>
- Carpenter Tutoring is proud to have service homeschooling communities in Virginia and North Carolina since 2019.
+ We are proud to continue serving homeschooling families with a variety of services.
</p>
<p>
@@ -142,7 +140,7 @@
<em>Detailed Evaluations</em> include all the elements of Simplified Evaluations plus the option to add subjects
beyond math and language arts and a second letter intended for use only by families which identifies areas of
strength and weakness in the subjects provided and recommendations for moving forward. Please <a
- href="/#contact">contact us</a> for more information.
+ href="#contact">contact us</a> for more information.
</p>
</section>
@@ -197,23 +195,26 @@
<li>Personal Finance</li>
</ul>
- Support may be available for courses beyond those listed. Please <a href="/#contact">contact us</a> for more
+ Support may be available for courses beyond those listed. Please <a href="#contact">contact us</a> for more
information.
</p>
<h6>Science</h6>
<p>
- <aside>* High school classes offered at regular level only for content support; studying and organizational support
+ <aside>High school classes offered at regular level only for content support; studying and organizational support
available for higher levels.</aside>
<ul>
<li>Elementary Science</li>
<li>Intermediate Science</li>
<li>Middle School Science</li>
- <li>Biology</li>
+ <li>AP and non-AP Biology</li>
+ <li>Physiology/Anatomy</li>
<li>Physics</li>
- <li>Chemistry</li>
+ <li>Organic Chemistry</li>
+ <li>AP and non-AP Chemistry</li>
<li>Environmental Science</li>
+ <li>Life Sciences</li>
<li>Earth Science</li>
</ul>
</p>
@@ -236,9 +237,9 @@
<h6>Language Arts / English</h6>
<p>
<ul>
- <li>Elementary level </li>
- <li>Intermediate level </li>
- <li>Middle School level </li>
+ <li>Elementary Language Arts </li>
+ <li>Intermediate Language Arts </li>
+ <li>Middle School Language Arts </li>
<li>English I or 9</li>
<li>English II or 10 </li>
<li>English III or 11 </li>
@@ -254,9 +255,35 @@
<h6> Computer Science </h6>
<p>
Computer science course content and offerings vary widely by school. A professional software engineer is
- available to discuss support options for specific needs. Please <a href="/#contact">contact us</a> for more
+ available to discuss support options for specific needs. Please <a href="#contact">contact us</a> for more
information.
</p>
</section>
+<section id="reviews" class="cards">
+ {% let name = "T.H.S." %}
+ {% let title = "Subject Tutoring parent" %}
+ {% let quote = "Carpenter Tutoring is an excellent choice if you want your student to progress in any subject with confidence. My daughter went from dreading Latin to meeting the challenge of translating and memorizing vocabulary with confidence. Ms. Carpenter is a consummate professional and an excellent communicator with parents and students. We will continue to use Carpenter Tutoring when necessary." %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Nichole C." %}
+ {% let title = "Subject Tutoring parent & client" %}
+ {% let quote = "I will share that when we were 1st looking for a tutor, I wasn't sure what we needed but help with math. Once we met and you started tutoring my kids, you are so wonderful in how you teach both of them. With my daughter, she was a lost soul with math. She now understands math in a way that I don't think I could have helped her. The way you teach, explain and show how math is done, is simply AMAZING. When it came time for my son to need help with Math, I knew you were the one to do it! Why? It's the way you are patient, kind and so helpful in allowing them to learn math in a way that benefits my kids." %}
+ {% let stars = 0 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Kris C." %}
+ {% let title = "Services for Homeschoolers & Subject Tutoring parent" %}
+ {% let quote = " Amy is invaluable to us as our homeschool teacher. She has a wealth of knowledge in many different subjects and working with students comes easily to her." %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+
+ {% let name = "Noel M." %}
+ {% let title = "Services for Homeschoolers parent" %}
+ {% let quote = " Amy is absolutely outstanding! We have used her for my daughter's proof of progress evaluator [since 2022] and I cannot give her enough praise! I recommend her to all my homeschooling friends as an evaluator. She is always extremely professional, kind, and organized. Her online system for portfolio evaluations is user friendly and makes my job of putting together the portfolio carefree. Once I have submitted it to her, she sends me my letter needed for proof of progress within 2-3 days! Her proof of progress letters are also thorough and professional. I cannot thank her enough each year and you will not regret using her!" %}
+ {% let stars = 5 %}
+ {% include "review.html.j2" %}
+</section>
+
{% endblock %} \ No newline at end of file
diff --git a/templates/policies.html b/templates/policies.html.j2
index 6a5754a..c0fc1ed 100644
--- a/templates/policies.html
+++ b/templates/policies.html.j2
@@ -1,10 +1,11 @@
-{% extends "base.html" %}
+{% extends "base.html.j2" %}
{% block main %}
<section class="banner">
<h1>Policies &amp; Procedures</h1>
</section>
+
<section>
<p>
<h2>Payment Methods</h2>
@@ -365,6 +366,4 @@
</ul>
</section>
-<section></section>
-
{% endblock %} \ No newline at end of file
diff --git a/templates/post.html b/templates/post.html.j2
index 9eb3444..3d5c7aa 100644
--- a/templates/post.html
+++ b/templates/post.html.j2
@@ -1,4 +1,4 @@
-{% extends "base.html" %}
+{% extends "base.html.j2" %}
{% block title %}
{{ post.get_title() }} - Carpenter Tutoring, LLC
@@ -8,7 +8,7 @@
<meta name="description" content="{{ post.get_description() }}" />
<meta property="og:description" content="{{ post.get_description() }}" />
<meta property="og:title" content="{{ post.get_title() }}" />
-<meta property="og:url" content="https://carpentertutoring.com/posts/{{ post.get_title()|e }}" />
+<meta property="og:url" content="https://carpentertutoring.com/blog/{{ post.get_title()|e }}" />
{% endblock %}
{% block main %}
@@ -18,7 +18,7 @@
<section>
<article>
- {{ post.get_article()|markdown }}
+ {{ post.get_article() | safe }}
</article>
</section>
{% endblock %} \ No newline at end of file
diff --git a/templates/posts.html b/templates/posts.html
deleted file mode 100644
index 2f1df6b..0000000
--- a/templates/posts.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% extends "base.html" %}
-
-{% block main %}
-<section class="banner">
- <h1>Posts</h1>
-</section>
-
-<section>
- <p>
- {% for post in posts %}
- <h2><a href="/posts/{{ post.get_title()|e }}">{{ post.get_title() }}</a></h2>
- {% endfor %}
- </p>
- <section>
- {% endblock %} \ No newline at end of file
diff --git a/templates/posts.html.j2 b/templates/posts.html.j2
new file mode 100644
index 0000000..8352d7e
--- /dev/null
+++ b/templates/posts.html.j2
@@ -0,0 +1,25 @@
+{% extends "base.html.j2" %}
+
+{% block main %}
+<section class="banner flexible">
+ <h1>Blog</h1>
+ <h6>
+ Sharing reflections and recommendations from practice
+ </h6>
+</section>
+
+<section class="cards">
+ {% for post in posts %}
+ <div class="card">
+ <h6>
+ {{ post.get_title()|e }}
+ </h6>
+ <p>
+ {{ post.get_description()|safe }}
+ </p>
+
+ <a target="_blank" href="/blog/{{ post.get_title()|e }}">Read more</a>
+ </div>
+ {% endfor %}
+</section>
+{% endblock %} \ No newline at end of file
diff --git a/templates/pro.html.j2 b/templates/pro.html.j2
new file mode 100644
index 0000000..e9b8fe6
--- /dev/null
+++ b/templates/pro.html.j2
@@ -0,0 +1,80 @@
+{% extends "base.html.j2" %}
+
+{% block main %}
+
+<section class="banner flexible">
+ <h1>Services for Professionals</h1>
+ <h6>
+ Planning, writing, editing, and thought partnership for professionals of all fields and levels.
+ </h6>
+</section>
+
+<section id="offerings" class="cards">
+ <div class="card full">
+ <h3>
+ Services for Professionals
+ </h3>
+ </div>
+
+ <div class="card">
+ <p> <a href="#offering-leadership-mentoring">Leadership Mentoring</a></p>
+ </div>
+
+ <div class="card">
+ <p> <a href="#offering-time-management-coaching">Time Management Coaching</a></p>
+ </div>
+
+ <div class="card">
+ <p> <a href="#offering-writing-support">Writing Support</a></p>
+ </div>
+</section>
+
+<section id="offering-leadership-mentoring">
+ <h2>Leadership Mentoring</h2>
+
+ <p>
+ Making decisions, navigating workplace politics, and guiding the people who work below and alongside you aren't
+ easy&mdash;especially if you're facing them alone. By partnering with a confidential mentor outside your
+ organization, you can discuss your situation free of office politics, receive and consider
+ different perspectives, and gain a sounding board in weighing different courses of action. Leadership mentoring
+ teaches healthy processes for decision-making and managing difficult situations so professionals can lead with
+ confidence.
+ </p>
+</section>
+
+<section id="offering-time-management-coaching">
+ <h2>Time Management Coaching</h2>
+
+ <p>
+ Time Management Coaching teaches and models the skills professionals need to navigate the demands of their
+ careers. We work together to create and execute realistic plans to handle the responsibilities of each week.
+ Tailored to each client's individual needs, Time Management Coaching provides a partner in navigating both
+ professional and personal responsibilities with the goal of decreasing stress and increasing confidence,
+ autonomy, and self-sufficiency. Topics covered include but are not limited to
+
+ <ul>
+ <li>Time and stress management </li>
+ <li>Task prioritization </li>
+ <li>Organization </li>
+ <li>Motivation </li>
+ <li>Overcoming procrastination </li>
+ <li>Self-advocacy </li>
+ <li>Communication </li>
+ <li>Understanding supervisor expectations</li>
+ </ul>
+ </p>
+</section>
+
+<section id="offering-writing-support">
+ <h2>Writing Support</h2>
+
+ <p>
+ A clear message, appropriate tone, and well-supported points are vital for successful writing in a professional
+ setting. Whether you're writing a delicate email, an annual report, a request for funding, or anything in
+ between, this offering will help you anticipate and circumvent possible misinterpretations of your writing,
+ identify areas to strengthen your message or evidence, and adopt a tone suited to your audience and situation.
+ On-going coaching relationships for general writing support as well as editing services are available.
+ </p>
+</section>
+
+{% endblock %} \ No newline at end of file
diff --git a/templates/review.html.j2 b/templates/review.html.j2
new file mode 100644
index 0000000..96dfde1
--- /dev/null
+++ b/templates/review.html.j2
@@ -0,0 +1,21 @@
+<div class="card">
+ <h2>{{ name }}</h2>
+
+ <h3>{{ title }}</h3>
+
+ {% if stars > 0 %}
+ {% for star in 0..stars %}
+ <img src="/assets/icons/star-box.svg" alt="star" />
+ {% endfor %}
+ {% else %}
+ <em>Email testimonial</em>
+ {% endif %}
+
+ <blockquote>
+ {{ quote }}
+ </blockquote>
+
+ <p>
+ <a href="https://g.page/carpenter-tutoring/review?np">Leave a review</a>
+ </p>
+</div> \ No newline at end of file