diff options
44 files changed, 1532 insertions, 1044 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..74bf340 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,46 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'carpentertutoring'", + "cargo": { + "args": [ + "build", + "--bin=carpentertutoring", + "--package=carpentertutoring" + ], + "filter": { + "name": "carpentertutoring", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}", + "preLaunchTask": "rust: cargo build", + "env": { + "CT_BIND": "0.0.0.0:8001" + } + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'carpentertutoring'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=carpentertutoring", + "--package=carpentertutoring" + ], + "filter": { + "name": "carpentertutoring", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +}
\ No newline at end of file @@ -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", +] @@ -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 800d8f8..aa36e15 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -1,15 +1,18 @@ -use askama::Template; -use crate::views::post::PostView; -use crate::views::posts::PostsView; use crate::posts::abstractions::repo::PostRepo; -use crate::views::policies::PoliciesTemplate; -use crate::views::index::IndexTemplate; -use crate::views::brochure::BrochureTemplate; -use crate::views::about::AboutView; 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, Redirect}; use std::sync::Arc; -use axum::response::Html; -use axum::extract::{State, Path}; pub async fn about_handler(State(repo): State<Arc<impl TutorRepo>>) -> Html<String> { let view = AboutView::with_tutors(repo.load()); @@ -17,7 +20,7 @@ pub async fn about_handler(State(repo): State<Arc<impl TutorRepo>>) -> Html<Stri } pub async fn brochure_handler() -> Html<String> { - Html(BrochureTemplate{}.render().unwrap()) + Html(BrochureTemplate {}.render().unwrap()) } pub async fn index_handler() -> Html<String> { @@ -25,7 +28,7 @@ pub async fn index_handler() -> Html<String> { } pub async fn policies_handler() -> Html<String> { - Html(PoliciesTemplate{}.render().unwrap()) + Html(PoliciesTemplate {}.render().unwrap()) } pub async fn posts_handler(State(repo): State<Arc<impl PostRepo>>) -> Html<String> { @@ -33,8 +36,26 @@ pub async fn posts_handler(State(repo): State<Arc<impl PostRepo>>) -> Html<Strin Html(view.render().unwrap()) } -pub async fn post_handler(Path(post_id): Path<String>, State(repo): State<Arc<impl PostRepo>>) -> Html<String> { +pub async fn post_handler( + Path(post_id): Path<String>, + State(repo): State<Arc<impl PostRepo>>, +) -> Html<String> { let view = PostView::with_post(repo.by_id(&post_id)); 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 372915b..a9cd722 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,24 @@ +use axum::response::Redirect; +use axum::{extract::Request, routing::get, Router, ServiceExt}; +use middleware::cache_control::cache_static; +use posts::fs_post_repo::FsPostRepo; +use std::{env, sync::Arc}; use tower::Layer; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; -use tower_http::{trace::{self, TraceLayer}, normalize_path::NormalizePathLayer}; +use tower_http::services::ServeDir; +use tower_http::{ + normalize_path::NormalizePathLayer, + trace::{self, TraceLayer}, +}; use tracing::{info, Level}; -use axum::{routing::get, Router, ServiceExt, extract::Request}; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; use tutors::fs_tutor_repo::FsTutorRepo; -use std::{sync::Arc, env}; -use tower_http::services::ServeDir; -use posts::fs_post_repo::FsPostRepo; -use middleware::cache_control::cache_static; +mod handlers; mod helpers; +mod middleware; mod posts; mod tutors; mod views; -mod handlers; -mod middleware; #[tokio::main] async fn main() { @@ -28,9 +32,9 @@ async fn main() { .init(); info!("loading state..."); - let blog_dir = env::var("CT_POSTS").unwrap(); - let tutor_dir = env::var("CT_TEAM").unwrap(); - let assets_dir = env::var("CT_ASSETS").unwrap(); + let blog_dir = env::var("CT_POSTS").unwrap_or(String::from("/var/ct/posts")); + let tutor_dir = env::var("CT_TEAM").unwrap_or(String::from("/var/ct/team")); + let assets_dir = env::var("CT_ASSETS").unwrap_or(String::from("/var/ct/assets")); let posts = Arc::new(FsPostRepo::with_dir(blog_dir)); let tutors = Arc::new(FsTutorRepo::with_dir(tutor_dir.clone())); @@ -38,12 +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)) @@ -51,14 +60,14 @@ async fn main() { .layer(axum::middleware::from_fn(cache_static)) .layer( TraceLayer::new_for_http() - .make_span_with(trace::DefaultMakeSpan::new() - .level(Level::INFO)) - .on_response(trace::DefaultOnResponse::new() - .level(Level::INFO)) + .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) + .on_response(trace::DefaultOnResponse::new().level(Level::INFO)), ); let app = NormalizePathLayer::trim_trailing_slash().layer(app); let addr = env::var("CT_BIND").unwrap_or("0.0.0.0:8000".into()); let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); - axum::serve(listener, ServiceExt::<Request>::into_make_service(app)).await.unwrap(); + axum::serve(listener, ServiceExt::<Request>::into_make_service(app)) + .await + .unwrap(); } diff --git a/src/middleware/cache_control.rs b/src/middleware/cache_control.rs index 30f31ca..0f11924 100644 --- a/src/middleware/cache_control.rs +++ b/src/middleware/cache_control.rs @@ -3,7 +3,7 @@ use axum::http::header::{HeaderValue, CACHE_CONTROL}; use axum::middleware::Next; use axum::response::Response; -pub async fn cache_static(mut request: Request, next: Next) -> Response { +pub async fn cache_static(request: Request, next: Next) -> Response { let was_static = request.uri().path().starts_with("/assets"); let mut response = next.run(request).await; diff --git a/src/posts/fs_post.rs b/src/posts/fs_post.rs index 6023c40..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,18 +21,20 @@ 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> { let article = self.get_article(); Cow::Owned( article - .split_once("\n") + .split_once('\n') .map(|(first, _)| first) .unwrap_or_default() .trim_start_matches('_') .trim_start_matches('*') + .trim_end_matches('_') + .trim_end_matches('*') .to_owned(), ) } 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 cb58813..f880818 100644 --- a/src/views.rs +++ b/src/views.rs @@ -1,6 +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 new file mode 100644 index 0000000..c7dc019 --- /dev/null +++ b/src/views/k12.rs @@ -0,0 +1,6 @@ +use crate::helpers::*; +use askama::Template; + +#[derive(Template)] +#[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 7a20b0a..cdfcd34 100644 --- a/static/desktop.css +++ b/static/desktop.css @@ -1,37 +1,24 @@ @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 { margin: 0; padding: 0; top: 0; - width: 100%; } div.buttons { - flex-direction: row-reverse; - } - - .banner { - padding-top: 7em; - text-align: right; - background: linear-gradient( - to right, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 1) 50% - ); - } - - form { - margin-right: 10%; - margin-left: 10%; - } - - table td, - table th { - padding: 0.5em; + flex-direction: row; + justify-content: center; } section.flexible { @@ -51,10 +38,6 @@ flex-grow: 1; } - .signature img { - width: 30%; - } - .logo img { width: 15%; display: block; @@ -63,17 +46,11 @@ } .card { - padding: 2em; - } - - #reviews .card, - #offerings .card { - display: block; - flex: none; - width: 20%; + 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 new file mode 100644 index 0000000..adafa42 --- /dev/null +++ b/static/linkchecker-out.sitemap.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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 --> + +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> + <url> + <loc>https://carpentertutoring.com</loc> + <changefreq>daily</changefreq> + <priority>1.00</priority> + </url> + <url> + <loc>https://carpentertutoring.com/</loc> + <changefreq>daily</changefreq> + <priority>0.50</priority> + </url> + <url> + <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> + <url> + <loc>https://carpentertutoring.com/brochure</loc> + <changefreq>daily</changefreq> + <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> + </url> + <url> + <loc>https://carpentertutoring.com/about</loc> + <changefreq>daily</changefreq> + <priority>0.50</priority> + </url> + <url> + <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/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-06-04 22:23:29-004 (11 seconds) --> diff --git a/templates/styles.css b/static/styles.css index a0d9a80..5fcdfe9 100644 --- a/templates/styles.css +++ b/static/styles.css @@ -23,20 +23,16 @@ body { body { background-image: url("/assets/bg.webp"); -} - -.banner { - font-size: 1em; - text-align: center; - padding: 3em; - background-color: white; + background-size: 9em; } nav { display: flex; flex-wrap: wrap; background-color: white; - position: fixed; + position: fixed; + width: 100%; + z-index: 1; } nav img { @@ -50,6 +46,7 @@ nav a { text-decoration: none; padding: 1em 1em; transition: 0.15s; + cursor: pointer; } nav a:hover { @@ -88,18 +85,23 @@ em { } section { - font-size: 1.5em; - margin: 0; + font-size: 1em; + margin-top: 0; + margin-right: 0; + margin-left: 0; + margin-bottom: 2em; padding: 1em; -} - -section.quiet { background-color: white; } -section.squarshed { +section.banner { + text-align: center; + 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 { @@ -145,7 +147,7 @@ footer { } footer p { - font-size: 1.5em; + font-size: 1em; } footer a, @@ -154,15 +156,6 @@ section a { text-decoration: underline; } -.card { - font-size: 0.9em; - background-color: white; - padding: 1em; - border-radius: 1em; - margin-left: 0; - margin-right: 0; -} - form input, form textarea { font-family: "PT Sans", sans-serif; @@ -182,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%; } @@ -229,14 +194,8 @@ section.flexible { flex-direction: column; } -#reviews .card, -#offerings .card { - margin: 1em; - text-align: center; -} - -#reviews, -#offerings { +section.cards { + background-color: transparent; padding-left: 0; padding-right: 0; display: flex; @@ -244,41 +203,33 @@ section.flexible { justify-content: center; } -.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 0d2434a..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="quiet 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="quiet flexible squarshed"> +<section class="flexible"> <figure class="shadowy"> <picture> <source srcset="/assets/amy.webp" type="image/webp" /> @@ -64,8 +62,6 @@ </section> -<section></section> +{% include "team.html.j2" %} -{% include "team.html" %} - -{% endblock %} +{% endblock %}
\ No newline at end of file diff --git a/templates/about/team.html b/templates/about/team.html deleted file mode 100644 index 2857efe..0000000 --- a/templates/about/team.html +++ /dev/null @@ -1,13 +0,0 @@ -{% for tutor in tutors %} -<section class="quiet flexible"> - {% if loop.index0 % 2 == 0 %} - {% include "blurb.html" %} - {% include "figure.html" %} - {% else %} - {% include "figure.html" %} - {% include "blurb.html" %} - {% endif %} -</section> - -<section></section> -{% endfor %} 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 b051c0f..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,26 +31,26 @@ <!-- 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> <body> <nav> <a href="/#"><img alt="logo" src="/assets/logo-simple.png" /></a> - <a href="/#offerings">Services</a> - <a href="/posts">Posts</a> + <a href="/k12">K-12</a> + <a href="/highered">Higher Ed</a> + <a href="/professional">Pros</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="#">More…</a> + <a href="#contact">Contact</a> + <a>More…</a> </nav> <main> @@ -64,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> - © 2019-{{ self::current_year() }} Carpenter Tutoring, LLC. All rights reserved. + © 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> @@ -87,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 deleted file mode 100644 index 41a62f4..0000000 --- a/templates/brochure/index.html +++ /dev/null @@ -1,32 +0,0 @@ -{% extends "base.html" %} - -{% block style %} - {% include "../styles.css" %} - {% include "brochure.css" %} -{% endblock %} - -{% block main %} -<section class="banner"> - <h1>Interactive Brochure</h1> -</section> - -<section class="quiet"> - <noscript> - This brochure requires JavaScript to work properly. If you prefer not to use JavaScript, you can <a href="/#offerings">view our offerings on our homepage here.</a> - </noscript> - - <p> - Click on pages to fold and unfold and use <em>Flip</em> to toggle front and back. This works best on a tablet or desktop screen. - </p> - - {% include "brochure.html" %} - -</section> - -<section></section> - -<script> - {% include "brochure.js" %} -</script> - -{% endblock %} diff --git a/templates/brochure/index.html.j2 b/templates/brochure/index.html.j2 new file mode 100644 index 0000000..a3a5b33 --- /dev/null +++ b/templates/brochure/index.html.j2 @@ -0,0 +1,32 @@ +{% extends "base.html.j2" %} + +{% block styles %} +<link rel="stylesheet" href="/styles.css" /> +<link rel="stylesheet" href="/brochure.css" /> +{% endblock %} + +{% block main %} +<section class="banner"> + <h1>Interactive Brochure</h1> +</section> + +<section> + <noscript> + This brochure requires JavaScript to work properly. If you prefer not to use JavaScript, you can <a + href="/#offerings">view our offerings on our homepage here.</a> + </noscript> + + <p> + Click on pages to fold and unfold and use <em>Flip</em> to toggle front and back. This works best on a tablet or + desktop screen. + </p> + + {% include "brochure.html.j2" %} + +</section> + +<script> + {% include "brochure.js" %} +</script> + +{% endblock %}
\ 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..0463826 --- /dev/null +++ b/templates/highered.html.j2 @@ -0,0 +1,169 @@ +{% 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> + </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 72b0892..0000000 --- a/templates/index.html +++ /dev/null @@ -1,361 +0,0 @@ -{% extends "base.html" %} - -{% block main %} -<!--banner--> -<section class="banner"> - <h1>CARPENTER TUTORING</h1> - <h2> - <strong>Discovering <em>your</em> path to success</strong> - </h2> - - <div class="buttons"> - {% include "contact-buttons.html" %} - </div> -</section> - -<!-- welcome--> -<section id="welcome" class="quiet flexible"> - <div> - <h2> - Welcome, and thank you for your interest in Carpenter Tutoring! - </h2> - - <p> Carpenter Tutoring is a private tutoring service based in Suffolk, - Virginia. We offer high-engagement remote appointments through Zoom. A limited - number of in-person appointments with me are also available for students in the Harbour - View region of Suffolk, VA. Most of our offerings are one-on-one, and siblings - and pre-existing groups of students may opt for group meetings. No matter your - budget, I am confident that we can find an arrangement that will provide your - student services without creating financial strain. </p> - - <p> - I invite you to explore and learn more about the <a href="/#offerings">services we offer</a>, <a href="/about">Carpenter Tutoring's background</a>, - and some of <a href="/policies">our policies</a>. Thank you for visiting, and - please do not hesitate to reach out with any questions. We will be thrilled to - assist you! - </p> - - <figure class="signature"> - <picture> - <source srcset="/assets/signature.webp" type="image/webp" /> - <source srcset="/assets/signature.png" type="image/png" /> - <img alt="Amy's signature" src="/assets/signature.png" /> - </picture> - </figure> - - </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> - -<!-- offering modals --> -<div id="offering-subject-tutoring" class="modal"> - <div class="card"> - <p> - Our regular subject specific offerings include: - - <ul> - <li> All levels of reading/language arts/English</li> - <li> Writing (formal and creative)</li> - <li> Foreign Language: French and all levels of Latin</li> - <li> Math through Calculus II</li> - <li> Introductory Physics (not at the honors or AP level)</li> - <li> Biology and Chemistry through AP level</li> - </ul> - - Special arrangements can be made for subjects that fall outside of these - offerings. Please contact me directly for more information. - - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-college-prep" class="modal"> - <div class="card"> - <p> - Work with a former Higher Education professional to - determine what types of schools and/or degree programs may be a good fit - for your interests and desires. Additionally, learn how to write an - attention-grabbing personal essay for college applications and receive - guidance on institution-specific supplemental essays. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-test-prep" class="modal"> - <div class="card"> - <p> - One-on-one content instruction, practice testing, and - testing strategization for a number of standardized tests, including but - not limited to: - - <ul> - <li> SAT & ACT</li> - <li> PSAT</li> - <li> ISEE</li> - <li> SSAT</li> - <li> GED</li> - <li> GMAT</li> - <li> MAT</li> - <li> GRE</li> - <li> LSAT</li> - </ul> - - Please contact me directly if you'd like assistance for a test not listed - here. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-music-lessons" class="modal"> - <div class="card"> - <p> - Piano lessons include a combination of formal instruction and - ear-training, which allows students to select the songs they'd like to - learn. Music composition lessons focus on the techniques necessary for - writing original songs, whether they be instrumental or singer/songwriter - style. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-evals" class="modal"> - <div class="card"> - <p> - Both evaluations are based on materials submitted through an online - portal. Letters are returned within a week of your notice that all documents - have been uploaded.</p> - <p> <strong>Simplified</strong>: Considers math and language arts materials, - satisfies proof of progress with a personalized letter and evaluator - credentials </p> - <p><strong>Detailed</strong>: Considers math and language arts materials - satisfies proof of progress with a - personalized letter and evaluator credentials, provides homeschool families - with a separate document detailing identified areas of strength, areas of - weakness, and recommendations for addressing weaknesses. - Other subjects may be added for an additional charge. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-college-writing" class="modal"> - <div class="card"> - <p> - Learn how to shift high-school level writing to that which will be expected in - college. Topics covered include moving beyond the five-paragraph essay, writing - research papers, and choosing a topic for essays with open prompts. In-session - exercises will allow students to implement these skills in real time with - immediate feedback. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-academic-coaching" class="modal"> - <div class="card"> - <p> - Academic Coaching offers all the benefits of Study Skills and Time Management - appointments plus ongoing planning and accountability support. As an Academic - Coach, I keep track of your student's upcoming assignments and assessments and - help craft a schedule week to week for them to accomplish their goals. Students - come away as more independent and confident planners and self-advocates. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-study-skills" class="modal"> - <div class="card"> - <p> - Study Skills sessions will allow students to develop a toolkit for - successful study habits. Learn about techniques to fight mental fatigue and - tools for mental recall. Study Skills sessions also cover ways to address - motivation, attention, and avoidance. Topics will be tailored for your specific - needs. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-dissertation-coaching" class="modal"> - <div class="card"> - <p> - Dissertation coaching consists of one-on-one work to strengthen the effort you - have already put in. Draw out the significance of your research by honing in on - the implications, connections, and recommendations that stem from your - findings. Together, we will break past a surface-level review of your study to - generate the greatest impact possible. Dissertation coaching can also focus on - general writing mechanics, clarity of message, and/or consistency of voice. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<div id="offering-time-management" class="modal"> - <div class="card"> - <p> - Learn how to balance all of the demands in your life. Time - Management sessions are tailored to your needs and can include building an - hour-by-hour schedule of your week, creating a long-term plan for assignments - and responsibilities, and discussing time and stress management techniques. - </p> - <a href="#offerings" class="button"><img src="/assets/icons/close-box.svg" alt="close" />Close</a> - </div> -</div> - -<!-- offerings cards --> -<section id="offerings"> - - <div class="card"> - <h2>Subject Tutoring</h2> - <p>Tutoring for specific courses or disciplines - </p> - <a class="button" href="#offering-subject-tutoring"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>Time Management</h2> - <p> - Personalized plans for managing academics, extracurriculars, and - other commitments - </p> - <a class="button" href="#offering-time-management"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>Study Skills</h2> - <p>Learn how to make the most of your study time</p> - <a class="button" href="#offering-study-skills"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>Academic Coaching</h2> - <p> - Time management and study skills blended with continuing - accountability - </p> - <a class="button" href="#offering-academic-coaching"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>College Application Assistance</h2> - <p> - Assistance with generating a college list and crafting application - essays - </p> - <a class="button" href="#offering-college-prep"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>College-Level Writing</h2> - <p>Get a head start on meeting professors' expectations</p> - <a class="button" href="#offering-college-writing"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>Dissertation Coaching</h2> - <p>Ensure your research is communicated effectively and eloquently</p> - <a class="button" href="#offering-dissertation-coaching"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>Standardized Test Prep</h2> - <p> - Tailored assistance in preparing for a variety of standardized tests - </p> - <a class="button" href="#offering-test-prep"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>Music Lessons</h2> - <p>Piano and/or composition lessons for students of all ages</p> - <a class="button" href="#offering-music-lessons"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - - <div class="card"> - <h2>Proof of Progress Evaluations</h2> - <p> - Two levels of portfolio-based evaluations for homeschool families - looking to satisfy Proof of Progress or gain insight into their - child's learning - </p> - <a class="button" href="#offering-evals"><img src="/assets/icons/dots-horizontal-circle.svg" alt="expand" /> Learn more</a> - </div> - -</section> - -<!-- help --> -<section class="quiet 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 %} 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 & 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.j2 b/templates/k12.html.j2 new file mode 100644 index 0000000..df6c9b4 --- /dev/null +++ b/templates/k12.html.j2 @@ -0,0 +1,286 @@ +{% extends "base.html.j2" %} + +{% block main %} + +<section class="banner flexible"> + <h1>K-12 Services</h1> + <h6>See your student thrive with personalized support.</h6> +</section> + +<section id="offerings" class="cards"> + <div class="card full"> + <h3> + K-12 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-services-for-homeschoolers"> + Services for Homeschoolers + </a> + </p> + </div> + + <div class="card"> + <p> + <a href="#offering-standardized-test-prep"> + Standardized Test Prep + </a> + </p> + </div> + + <div class="card"> + <p> + <a href="#offering-subject-tutoring"> + Subject Tutoring + </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 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> + </ul> + </p> +</section> + +<section id="offering-application-essay-consulting"> + <h2> + Application Essay Consulting + </h2> + + <p> + Whether you're applying to competitive high schools or getting ready for college, 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 <em>before</em> students arrive for + their first semester to ensure a smooth transition to college life. + </p> +</section> + +<section id="offering-services-for-homeschoolers"> + <h2> + Services for Homeschoolers + </h2> + + <p> + We are proud to continue serving homeschooling families with a variety of services. + </p> + + <p> + We offer both supplemental and primary instruction for a range of age levels and subjects. In both cases, we are + happy to adapt to your curricular choices. Please see <a href="#offering-subject-tutoring">Subject Tutoring</a> + for all subjects in which support is available. + </p> + + <p> + We also provide two levels of portfolio-based end-of-year Proof of Progress evaluations for families + homeschooling in Virginia. <em>Simplified Evaluations</em> consider math and language arts materials and satisfy + Virginia requirements with a personalized letter and evaluator credentials to be sent to the school system. + <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. + </p> +</section> + +<section id="offering-standardized-test-prep"> + <h2> + Standardized Test Prep + </h2> + + <p> + Individualized support in mastering both the content of and strategies for a number of standardized tests + including but not limited to + <ul> + <li>PSAT</li> + <li>SAT</li> + <li>ACT</li> + <li>SOLs</li> + <li>ISEE</li> + <li>SSAT</li> + <li>GED</li> + <li>ASVAB</li> + </ul> + </p> +</section> + +<section id="offering-subject-tutoring"> + <h2> + Subject Tutoring + </h2> + + <p> + Support offered for all applicable levels of courses (regular, Honors, AP) unless otherwise noted. + </p> + <p> + * indicates a specialized course for which support is dependent on team availability. + </p> + + <h6>Math</h6> + <p> + <ul> + <li>Elementary Math</li> + <li>Intermediate Math</li> + <li>Middle School Math</li> + <li>Pre-Algebra</li> + <li>Algebra I</li> + <li>Geometry</li> + <li>Algebra, Functions, and Data Analysis</li> + <li>Algebra 2</li> + <li>Algebra 3/Trigonometry</li> + <li>Probability and Statistics</li> + <li>Pre-Calculus</li> + <li>Calculus*</li> + <li>Personal Finance</li> + </ul> + + 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 + available for higher levels.</aside> + + <ul> + <li>Elementary Science</li> + <li>Intermediate Science</li> + <li>Middle School Science</li> + <li>Biology</li> + <li>Physics</li> + <li>Chemistry</li> + <li>Environmental Science</li> + <li>Earth Science</li> + </ul> + </p> + + <h6>Foreign Language</h6> + <p> + <ul> + <li>Latin I</li> + <li>Latin II</li> + <li>Latin III</li> + <li>Latin IV</li> + <li>Latin V</li> + <li>AP Latin IV</li> + </ul> + + Support may be available for courses and languages beyond those listed. Please <a href="/#contact">contact + us</a> for more information. + </p> + + <h6>Language Arts / English</h6> + <p> + <ul> + <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> + <li>English IV or 12 </li> + <li>AP Language and Composition </li> + <li>AP Literature and Composition </li> + <li>Creative Writing </li> + <li>General writing / grammar support </li> + <li>Editing</li> + </ul> + </p> + + <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 + 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 deleted file mode 100644 index 81a19a5..0000000 --- a/templates/policies.html +++ /dev/null @@ -1,250 +0,0 @@ -{% extends "base.html" %} - -{% block main %} - -<section class="banner"> - <h1>Policies & Procedures</h1> -</section> -<section class="quiet"> - <p> - <h2>Payment Methods</h2> - We accept payments through Zelle (amy@carpentertutoring.com), Venmo - (@AmyCTutoring), and PayPal (amy@carpentertutoring.com). We also accept - checks made out to Carpenter Tutoring, LLC. Please <a href="/#contact">contact Amy</a> for - a mailing address if you would like to pay by check. - </p> - - <p> - <h2>Travel</h2> - Due to high appointment volumes, Amy is only able to travel to students in the Harbour View area of Suffolk, VA. - </p> - - <p>Please contact other tutors directly to discuss their locations and in-person policies.</p> - - <p> - <h2>Remote sessions</h2> - Remote sessions are typically conducted from tutors' homes. We use online video conferencing software such as - <a target="_blank" href="https://zoom.us">Zoom</a> and <a target="_blank" href="https://meet.google.com">Google Meet</a>. - Your tutor will inform you of their preferred meeting method and provide initial meeting instructions and support. - </p> - - <p> - <h2>Late Cancellations</h2> - Sessions cancelled within 72 hours of their start time will incur a late - cancellation fee equal to 40% of the cancelled session price. - </p> - - <p> - <h2>No-Shows</h2> - Sessions which a student does not attend with no notice of - cancellation will be charged the full session price. - </p> - - <p> - <h2>Session Duration</h2> - Sessions are purchased in half-hour increments, and the shortest - appointment duration is 60 minutes. Families are responsible for the - amount of time they book and will be charged based on that amount. - Students who provide no advance notice of a need to end their meeting early will still be responsible for the full session price. If a student is - late to their appointment, we will work to the end of their scheduled - time, but no later. - </p> - - <p> - <h2>Proof of Progress Evaluations</h2> - Proof of Progress letters will be returned within 7 days of notification that materials are ready for review. Families are responsible for sending Proof of Progress letters and proof of evaluator credentials to their school system by August 1, the deadline for Proof of Progress submissions in Virginia. Notifications regarding sample readiness sent on or after July 24 of each year will incur a $10 late submission fee per evaluation. All payments are expected within two weeks of receipt of letter(s). Payment method information is available on this site as well as in the email sent along with Proof of Progress letters. - </p> - - <p> - <h2>Learning Acceleration Grants</h2> - Carpenter Tutoring is proud to serve Virginia students and families as a vendor for the K-12 Learning Acceleration Grant. Families must share student names as they appear on the grants, associated parent name, and associated address for invoicing purposes. Families are expected to upload emailed invoices at their earliest convenience as there are significant lag times between family submission and fund deposits from ClassWallet. While Carpenter Tutoring will provide an overview of funds used with our tutors with each invoice, families are expected to keep track of fund use and communicate with tutors when funds are nearing exhaustion to plan an end date for services or a transition to out-of-pocket payment. Grant vendors cannot see fund totals or funds used with other vendors, so we rely on families completely to communicate their remaining balances. Families who fail to notify us that their funds are nearly or have been depleted or rescinded but continue to use services will be required to pay for any excesses out-of-pocket. - </p> -</section> - -<section class="quiet"> - <h2>Privacy Policy</h2> - <p>Last updated: March 22, 2025</p> - <p>This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You.</p> - <p>We use Your Personal data to provide and improve the Service. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy. This Privacy Policy has been created with the help of the <a href="https://www.termsfeed.com/privacy-policy-generator/" target="_blank">Privacy Policy Generator</a>.</p> - <h3>Interpretation and Definitions</h3> - <h4>Interpretation</h4> - <p>The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural.</p> - <h4>Definitions</h4> - <p>For the purposes of this Privacy Policy:</p> - <ul> - <li> - <p><strong>Account</strong> means a unique account created for You to access our Service or parts of our Service.</p> - </li> - <li> - <p><strong>Affiliate</strong> means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.</p> - </li> - <li> - <p><strong>Company</strong> (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to Carpenter Tutoring LLC, 6205 Amberly Cir, Suffolk VA, 23435.</p> - </li> - <li> - <p><strong>Cookies</strong> are small files that are placed on Your computer, mobile device or any other device by a website, containing the details of Your browsing history on that website among its many uses.</p> - </li> - <li> - <p><strong>Country</strong> refers to: Virginia, United States</p> - </li> - <li> - <p><strong>Device</strong> means any device that can access the Service such as a computer, a cellphone or a digital tablet.</p> - </li> - <li> - <p><strong>Personal Data</strong> is any information that relates to an identified or identifiable individual.</p> - </li> - <li> - <p><strong>Service</strong> refers to the Website.</p> - </li> - <li> - <p><strong>Service Provider</strong> means any natural or legal person who processes the data on behalf of the Company. It refers to third-party companies or individuals employed by the Company to facilitate the Service, to provide the Service on behalf of the Company, to perform services related to the Service or to assist the Company in analyzing how the Service is used.</p> - </li> - <li> - <p><strong>Usage Data</strong> refers to data collected automatically, either generated by the use of the Service or from the Service infrastructure itself (for example, the duration of a page visit).</p> - </li> - <li> - <p><strong>Website</strong> refers to Carpenter Tutoring, accessible from <a href="https://carpentertutoring.com" rel="external nofollow noopener" target="_blank">https://carpentertutoring.com</a></p> - </li> - <li> - <p><strong>You</strong> means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.</p> - </li> - </ul> - <h3>Collecting and Using Your Personal Data</h3> - <h4>Types of Data Collected</h4> - <h5>Personal Data</h5> - <p>While using Our Service, We may ask You to provide Us with certain personally identifiable information that can be used to contact or identify You. Personally identifiable information may include, but is not limited to:</p> - <ul> - <li> - <p>Email address</p> - </li> - <li> - <p>First name and last name</p> - </li> - <li> - <p>Usage Data</p> - </li> - </ul> - <h5>Usage Data</h5> - <p>Usage Data is collected automatically when using the Service.</p> - <p>Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP address), browser type, browser version, the pages of our Service that You visit, the time and date of Your visit, the time spent on those pages, unique device identifiers and other diagnostic data.</p> - <p>When You access the Service by or through a mobile device, We may collect certain information automatically, including, but not limited to, the type of mobile device You use, Your mobile device unique ID, the IP address of Your mobile device, Your mobile operating system, the type of mobile Internet browser You use, unique device identifiers and other diagnostic data.</p> - <p>We may also collect information that Your browser sends whenever You visit our Service or when You access the Service by or through a mobile device.</p> - <h5>Tracking Technologies and Cookies</h5> - <p>We use Cookies and similar tracking technologies to track the activity on Our Service and store certain information. Tracking technologies used are beacons, tags, and scripts to collect and track information and to improve and analyze Our Service. The technologies We use may include:</p> - <ul> - <li><strong>Cookies or Browser Cookies.</strong> A cookie is a small file placed on Your Device. You can instruct Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do not accept Cookies, You may not be able to use some parts of our Service. Unless you have adjusted Your browser setting so that it will refuse Cookies, our Service may use Cookies.</li> - <li><strong>Web Beacons.</strong> Certain sections of our Service and our emails may contain small electronic files known as web beacons (also referred to as clear gifs, pixel tags, and single-pixel gifs) that permit the Company, for example, to count users who have visited those pages or opened an email and for other related website statistics (for example, recording the popularity of a certain section and verifying system and server integrity).</li> - </ul> - <p>Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your personal computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close Your web browser. You can learn more about cookies on <a href="https://www.termsfeed.com/blog/cookies/#What_Are_Cookies" target="_blank">TermsFeed website</a> article.</p> - <p>We use both Session and Persistent Cookies for the purposes set out below:</p> - <ul> - <li> - <p><strong>Necessary / Essential Cookies</strong></p> - <p>Type: Session Cookies</p> - <p>Administered by: Us</p> - <p>Purpose: These Cookies are essential to provide You with services available through the Website and to enable You to use some of its features. They help to authenticate users and prevent fraudulent use of user accounts. Without these Cookies, the services that You have asked for cannot be provided, and We only use these Cookies to provide You with those services.</p> - </li> - <li> - <p><strong>Cookies Policy / Notice Acceptance Cookies</strong></p> - <p>Type: Persistent Cookies</p> - <p>Administered by: Us</p> - <p>Purpose: These Cookies identify if users have accepted the use of cookies on the Website.</p> - </li> - <li> - <p><strong>Functionality Cookies</strong></p> - <p>Type: Persistent Cookies</p> - <p>Administered by: Us</p> - <p>Purpose: These Cookies allow us to remember choices You make when You use the Website, such as remembering your login details or language preference. The purpose of these Cookies is to provide You with a more personal experience and to avoid You having to re-enter your preferences every time You use the Website.</p> - </li> - </ul> - <p>For more information about the cookies we use and your choices regarding cookies, please visit our Cookies Policy or the Cookies section of our Privacy Policy.</p> - <h4>Use of Your Personal Data</h4> - <p>The Company may use Personal Data for the following purposes:</p> - <ul> - <li> - <p><strong>To provide and maintain our Service</strong>, including to monitor the usage of our Service.</p> - </li> - <li> - <p><strong>To manage Your Account:</strong> to manage Your registration as a user of the Service. The Personal Data You provide can give You access to different functionalities of the Service that are available to You as a registered user.</p> - </li> - <li> - <p><strong>For the performance of a contract:</strong> the development, compliance and undertaking of the purchase contract for the products, items or services You have purchased or of any other contract with Us through the Service.</p> - </li> - <li> - <p><strong>To contact You:</strong> To contact You by email, telephone calls, SMS, or other equivalent forms of electronic communication, such as a mobile application's push notifications regarding updates or informative communications related to the functionalities, products or contracted services, including the security updates, when necessary or reasonable for their implementation.</p> - </li> - <li> - <p><strong>To provide You</strong> with news, special offers and general information about other goods, services and events which we offer that are similar to those that you have already purchased or enquired about unless You have opted not to receive such information.</p> - </li> - <li> - <p><strong>To manage Your requests:</strong> To attend and manage Your requests to Us.</p> - </li> - <li> - <p><strong>For business transfers:</strong> We may use Your information to evaluate or conduct a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Our assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which Personal Data held by Us about our Service users is among the assets transferred.</p> - </li> - <li> - <p><strong>For other purposes</strong>: We may use Your information for other purposes, such as data analysis, identifying usage trends, determining the effectiveness of our promotional campaigns and to evaluate and improve our Service, products, services, marketing and your experience.</p> - </li> - </ul> - <p>We may share Your personal information in the following situations:</p> - <ul> - <li><strong>With Service Providers:</strong> We may share Your personal information with Service Providers to monitor and analyze the use of our Service, to contact You.</li> - <li><strong>For business transfers:</strong> We may share or transfer Your personal information in connection with, or during negotiations of, any merger, sale of Company assets, financing, or acquisition of all or a portion of Our business to another company.</li> - <li><strong>With Affiliates:</strong> We may share Your information with Our affiliates, in which case we will require those affiliates to honor this Privacy Policy. Affiliates include Our parent company and any other subsidiaries, joint venture partners or other companies that We control or that are under common control with Us.</li> - <li><strong>With business partners:</strong> We may share Your information with Our business partners to offer You certain products, services or promotions.</li> - <li><strong>With other users:</strong> when You share personal information or otherwise interact in the public areas with other users, such information may be viewed by all users and may be publicly distributed outside.</li> - <li><strong>With Your consent</strong>: We may disclose Your personal information for any other purpose with Your consent.</li> - </ul> - <h4>Retention of Your Personal Data</h4> - <p>The Company will retain Your Personal Data only for as long as is necessary for the purposes set out in this Privacy Policy. We will retain and use Your Personal Data to the extent necessary to comply with our legal obligations (for example, if we are required to retain your data to comply with applicable laws), resolve disputes, and enforce our legal agreements and policies.</p> - <p>The Company will also retain Usage Data for internal analysis purposes. Usage Data is generally retained for a shorter period of time, except when this data is used to strengthen the security or to improve the functionality of Our Service, or We are legally obligated to retain this data for longer time periods.</p> - <h4>Transfer of Your Personal Data</h4> - <p>Your information, including Personal Data, is processed at the Company's operating offices and in any other places where the parties involved in the processing are located. It means that this information may be transferred to — and maintained on — computers located outside of Your state, province, country or other governmental jurisdiction where the data protection laws may differ than those from Your jurisdiction.</p> - <p>Your consent to this Privacy Policy followed by Your submission of such information represents Your agreement to that transfer.</p> - <p>The Company will take all steps reasonably necessary to ensure that Your data is treated securely and in accordance with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or a country unless there are adequate controls in place including the security of Your data and other personal information.</p> - <h4>Delete Your Personal Data</h4> - <p>You have the right to delete or request that We assist in deleting the Personal Data that We have collected about You.</p> - <p>Our Service may give You the ability to delete certain information about You from within the Service.</p> - <p>You may update, amend, or delete Your information at any time by signing in to Your Account, if you have one, and visiting the account settings section that allows you to manage Your personal information. You may also contact Us to request access to, correct, or delete any personal information that You have provided to Us.</p> - <p>Please note, however, that We may need to retain certain information when we have a legal obligation or lawful basis to do so.</p> - <h4>Disclosure of Your Personal Data</h4> - <h5>Business Transactions</h5> - <p>If the Company is involved in a merger, acquisition or asset sale, Your Personal Data may be transferred. We will provide notice before Your Personal Data is transferred and becomes subject to a different Privacy Policy.</p> - <h5>Law enforcement</h5> - <p>Under certain circumstances, the Company may be required to disclose Your Personal Data if required to do so by law or in response to valid requests by public authorities (e.g. a court or a government agency).</p> - <h5>Other legal requirements</h5> - <p>The Company may disclose Your Personal Data in the good faith belief that such action is necessary to:</p> - <ul> - <li>Comply with a legal obligation</li> - <li>Protect and defend the rights or property of the Company</li> - <li>Prevent or investigate possible wrongdoing in connection with the Service</li> - <li>Protect the personal safety of Users of the Service or the public</li> - <li>Protect against legal liability</li> - </ul> - <h4>Security of Your Personal Data</h4> - <p>The security of Your Personal Data is important to Us, but remember that no method of transmission over the Internet, or method of electronic storage is 100% secure. While We strive to use commercially acceptable means to protect Your Personal Data, We cannot guarantee its absolute security.</p> - <h3>Children's Privacy</h3> - <p>Our Service does not address anyone under the age of 13. We do not knowingly collect personally identifiable information from anyone under the age of 13. If You are a parent or guardian and You are aware that Your child has provided Us with Personal Data, please contact Us. If We become aware that We have collected Personal Data from anyone under the age of 13 without verification of parental consent, We take steps to remove that information from Our servers.</p> - <p>If We need to rely on consent as a legal basis for processing Your information and Your country requires consent from a parent, We may require Your parent's consent before We collect and use that information.</p> - <h3>Links to Other Websites</h3> - <p>Our Service may contain links to other websites that are not operated by Us. If You click on a third party link, You will be directed to that third party's site. We strongly advise You to review the Privacy Policy of every site You visit.</p> - <p>We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services.</p> - <h3>Changes to this Privacy Policy</h3> - <p>We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy Policy on this page.</p> - <p>We will let You know via email and/or a prominent notice on Our Service, prior to the change becoming effective and update the "Last updated" date at the top of this Privacy Policy.</p> - <p>You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page.</p> - <h3>Contact Us</h3> - <p>If you have any questions about this Privacy Policy, You can contact us:</p> - <ul> - <li> - <p>By email: privacy@carpentertutoring.com</p> - </li> - <li> - <p>By visiting this page on our website: <a href="https://carpentertutoring.com/policies" rel="external nofollow noopener" target="_blank">https://carpentertutoring.com/policies</a></p> - </li> - </ul> -</section> - -<section></section> - -{% endblock %} diff --git a/templates/policies.html.j2 b/templates/policies.html.j2 new file mode 100644 index 0000000..c0fc1ed --- /dev/null +++ b/templates/policies.html.j2 @@ -0,0 +1,369 @@ +{% extends "base.html.j2" %} + +{% block main %} + +<section class="banner"> + <h1>Policies & Procedures</h1> +</section> + +<section> + <p> + <h2>Payment Methods</h2> + We accept payments through Zelle (amy@carpentertutoring.com), Venmo + (@AmyCTutoring), and PayPal (amy@carpentertutoring.com). We also accept + checks made out to Carpenter Tutoring, LLC. Please <a href="/#contact">contact Amy</a> for + a mailing address if you would like to pay by check. + </p> + + <p> + <h2>Travel</h2> + Due to high appointment volumes, Amy is only able to travel to students in the Harbour View area of Suffolk, VA. + </p> + + <p>Please contact other tutors directly to discuss their locations and in-person policies.</p> + + <p> + <h2>Remote sessions</h2> + Remote sessions are typically conducted from tutors' homes. We use online video conferencing software such as + <a target="_blank" href="https://zoom.us">Zoom</a> and <a target="_blank" href="https://meet.google.com">Google + Meet</a>. + Your tutor will inform you of their preferred meeting method and provide initial meeting instructions and support. + </p> + + <p> + <h2>Late Cancellations</h2> + Sessions cancelled within 72 hours of their start time will incur a late + cancellation fee equal to 40% of the cancelled session price. + </p> + + <p> + <h2>No-Shows</h2> + Sessions which a student does not attend with no notice of + cancellation will be charged the full session price. + </p> + + <p> + <h2>Session Duration</h2> + Sessions are purchased in half-hour increments, and the shortest + appointment duration is 60 minutes. Families are responsible for the + amount of time they book and will be charged based on that amount. + Students who provide no advance notice of a need to end their meeting early will still be responsible for the full + session price. If a student is + late to their appointment, we will work to the end of their scheduled + time, but no later. + </p> + + <p> + <h2>Proof of Progress Evaluations</h2> + Proof of Progress letters will be returned within 7 days of notification that materials are ready for review. + Families are responsible for sending Proof of Progress letters and proof of evaluator credentials to their school + system by August 1, the deadline for Proof of Progress submissions in Virginia. Notifications regarding sample + readiness sent on or after July 24 of each year will incur a $10 late submission fee per evaluation. All payments + are expected within two weeks of receipt of letter(s). Payment method information is available on this site as well + as in the email sent along with Proof of Progress letters. + </p> + + <p> + <h2>Learning Acceleration Grants</h2> + Carpenter Tutoring is proud to serve Virginia students and families as a vendor for the K-12 Learning Acceleration + Grant. Families must share student names as they appear on the grants, associated parent name, and associated + address for invoicing purposes. Families are expected to upload emailed invoices at their earliest convenience as + there are significant lag times between family submission and fund deposits from ClassWallet. While Carpenter + Tutoring will provide an overview of funds used with our tutors with each invoice, families are expected to keep + track of fund use and communicate with tutors when funds are nearing exhaustion to plan an end date for services or + a transition to out-of-pocket payment. Grant vendors cannot see fund totals or funds used with other vendors, so we + rely on families completely to communicate their remaining balances. Families who fail to notify us that their funds + are nearly or have been depleted or rescinded but continue to use services will be required to pay for any excesses + out-of-pocket. + </p> +</section> + +<section> + <h2>Privacy Policy</h2> + <p>Last updated: March 22, 2025</p> + <p>This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your + information when You use the Service and tells You about Your privacy rights and how the law protects You.</p> + <p>We use Your Personal data to provide and improve the Service. By using the Service, You agree to the collection + and use of information in accordance with this Privacy Policy. This Privacy Policy has been created with the + help of the <a href="https://www.termsfeed.com/privacy-policy-generator/" target="_blank">Privacy Policy + Generator</a>.</p> + <h3>Interpretation and Definitions</h3> + <h4>Interpretation</h4> + <p>The words of which the initial letter is capitalized have meanings defined under the following conditions. The + following definitions shall have the same meaning regardless of whether they appear in singular or in plural. + </p> + <h4>Definitions</h4> + <p>For the purposes of this Privacy Policy:</p> + <ul> + <li> + <p><strong>Account</strong> means a unique account created for You to access our Service or parts of our + Service.</p> + </li> + <li> + <p><strong>Affiliate</strong> means an entity that controls, is controlled by or is under common control + with a party, where "control" means ownership of 50% or more of the shares, equity interest or + other securities entitled to vote for election of directors or other managing authority.</p> + </li> + <li> + <p><strong>Company</strong> (referred to as either "the Company", "We", "Us" + or "Our" in this Agreement) refers to Carpenter Tutoring LLC, 6205 Amberly Cir, Suffolk VA, + 23435.</p> + </li> + <li> + <p><strong>Cookies</strong> are small files that are placed on Your computer, mobile device or any other + device by a website, containing the details of Your browsing history on that website among its many + uses.</p> + </li> + <li> + <p><strong>Country</strong> refers to: Virginia, United States</p> + </li> + <li> + <p><strong>Device</strong> means any device that can access the Service such as a computer, a cellphone or a + digital tablet.</p> + </li> + <li> + <p><strong>Personal Data</strong> is any information that relates to an identified or identifiable + individual.</p> + </li> + <li> + <p><strong>Service</strong> refers to the Website.</p> + </li> + <li> + <p><strong>Service Provider</strong> means any natural or legal person who processes the data on behalf of + the Company. It refers to third-party companies or individuals employed by the Company to facilitate the + Service, to provide the Service on behalf of the Company, to perform services related to the Service or + to assist the Company in analyzing how the Service is used.</p> + </li> + <li> + <p><strong>Usage Data</strong> refers to data collected automatically, either generated by the use of the + Service or from the Service infrastructure itself (for example, the duration of a page visit).</p> + </li> + <li> + <p><strong>Website</strong> refers to Carpenter Tutoring, accessible from <a + href="https://carpentertutoring.com" rel="external nofollow noopener" + target="_blank">https://carpentertutoring.com</a></p> + </li> + <li> + <p><strong>You</strong> means the individual accessing or using the Service, or the company, or other legal + entity on behalf of which such individual is accessing or using the Service, as applicable.</p> + </li> + </ul> + <h3>Collecting and Using Your Personal Data</h3> + <h4>Types of Data Collected</h4> + <h5>Personal Data</h5> + <p>While using Our Service, We may ask You to provide Us with certain personally identifiable information that can + be used to contact or identify You. Personally identifiable information may include, but is not limited to:</p> + <ul> + <li> + <p>Email address</p> + </li> + <li> + <p>First name and last name</p> + </li> + <li> + <p>Usage Data</p> + </li> + </ul> + <h5>Usage Data</h5> + <p>Usage Data is collected automatically when using the Service.</p> + <p>Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP address), browser + type, browser version, the pages of our Service that You visit, the time and date of Your visit, the time spent + on those pages, unique device identifiers and other diagnostic data.</p> + <p>When You access the Service by or through a mobile device, We may collect certain information automatically, + including, but not limited to, the type of mobile device You use, Your mobile device unique ID, the IP address + of Your mobile device, Your mobile operating system, the type of mobile Internet browser You use, unique device + identifiers and other diagnostic data.</p> + <p>We may also collect information that Your browser sends whenever You visit our Service or when You access the + Service by or through a mobile device.</p> + <h5>Tracking Technologies and Cookies</h5> + <p>We use Cookies and similar tracking technologies to track the activity on Our Service and store certain + information. Tracking technologies used are beacons, tags, and scripts to collect and track information and to + improve and analyze Our Service. The technologies We use may include:</p> + <ul> + <li><strong>Cookies or Browser Cookies.</strong> A cookie is a small file placed on Your Device. You can + instruct Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do + not accept Cookies, You may not be able to use some parts of our Service. Unless you have adjusted Your + browser setting so that it will refuse Cookies, our Service may use Cookies.</li> + <li><strong>Web Beacons.</strong> Certain sections of our Service and our emails may contain small electronic + files known as web beacons (also referred to as clear gifs, pixel tags, and single-pixel gifs) that permit + the Company, for example, to count users who have visited those pages or opened an email and for other + related website statistics (for example, recording the popularity of a certain section and verifying system + and server integrity).</li> + </ul> + <p>Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your personal + computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close Your web + browser. You can learn more about cookies on <a href="https://www.termsfeed.com/blog/cookies/#What_Are_Cookies" + target="_blank">TermsFeed website</a> article.</p> + <p>We use both Session and Persistent Cookies for the purposes set out below:</p> + <ul> + <li> + <p><strong>Necessary / Essential Cookies</strong></p> + <p>Type: Session Cookies</p> + <p>Administered by: Us</p> + <p>Purpose: These Cookies are essential to provide You with services available through the Website and to + enable You to use some of its features. They help to authenticate users and prevent fraudulent use of + user accounts. Without these Cookies, the services that You have asked for cannot be provided, and We + only use these Cookies to provide You with those services.</p> + </li> + <li> + <p><strong>Cookies Policy / Notice Acceptance Cookies</strong></p> + <p>Type: Persistent Cookies</p> + <p>Administered by: Us</p> + <p>Purpose: These Cookies identify if users have accepted the use of cookies on the Website.</p> + </li> + <li> + <p><strong>Functionality Cookies</strong></p> + <p>Type: Persistent Cookies</p> + <p>Administered by: Us</p> + <p>Purpose: These Cookies allow us to remember choices You make when You use the Website, such as + remembering your login details or language preference. The purpose of these Cookies is to provide You + with a more personal experience and to avoid You having to re-enter your preferences every time You use + the Website.</p> + </li> + </ul> + <p>For more information about the cookies we use and your choices regarding cookies, please visit our Cookies Policy + or the Cookies section of our Privacy Policy.</p> + <h4>Use of Your Personal Data</h4> + <p>The Company may use Personal Data for the following purposes:</p> + <ul> + <li> + <p><strong>To provide and maintain our Service</strong>, including to monitor the usage of our Service.</p> + </li> + <li> + <p><strong>To manage Your Account:</strong> to manage Your registration as a user of the Service. The + Personal Data You provide can give You access to different functionalities of the Service that are + available to You as a registered user.</p> + </li> + <li> + <p><strong>For the performance of a contract:</strong> the development, compliance and undertaking of the + purchase contract for the products, items or services You have purchased or of any other contract with + Us through the Service.</p> + </li> + <li> + <p><strong>To contact You:</strong> To contact You by email, telephone calls, SMS, or other equivalent forms + of electronic communication, such as a mobile application's push notifications regarding updates or + informative communications related to the functionalities, products or contracted services, including + the security updates, when necessary or reasonable for their implementation.</p> + </li> + <li> + <p><strong>To provide You</strong> with news, special offers and general information about other goods, + services and events which we offer that are similar to those that you have already purchased or enquired + about unless You have opted not to receive such information.</p> + </li> + <li> + <p><strong>To manage Your requests:</strong> To attend and manage Your requests to Us.</p> + </li> + <li> + <p><strong>For business transfers:</strong> We may use Your information to evaluate or conduct a merger, + divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Our + assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in + which Personal Data held by Us about our Service users is among the assets transferred.</p> + </li> + <li> + <p><strong>For other purposes</strong>: We may use Your information for other purposes, such as data + analysis, identifying usage trends, determining the effectiveness of our promotional campaigns and to + evaluate and improve our Service, products, services, marketing and your experience.</p> + </li> + </ul> + <p>We may share Your personal information in the following situations:</p> + <ul> + <li><strong>With Service Providers:</strong> We may share Your personal information with Service Providers to + monitor and analyze the use of our Service, to contact You.</li> + <li><strong>For business transfers:</strong> We may share or transfer Your personal information in connection + with, or during negotiations of, any merger, sale of Company assets, financing, or acquisition of all or a + portion of Our business to another company.</li> + <li><strong>With Affiliates:</strong> We may share Your information with Our affiliates, in which case we will + require those affiliates to honor this Privacy Policy. Affiliates include Our parent company and any other + subsidiaries, joint venture partners or other companies that We control or that are under common control + with Us.</li> + <li><strong>With business partners:</strong> We may share Your information with Our business partners to offer + You certain products, services or promotions.</li> + <li><strong>With other users:</strong> when You share personal information or otherwise interact in the public + areas with other users, such information may be viewed by all users and may be publicly distributed outside. + </li> + <li><strong>With Your consent</strong>: We may disclose Your personal information for any other purpose with + Your consent.</li> + </ul> + <h4>Retention of Your Personal Data</h4> + <p>The Company will retain Your Personal Data only for as long as is necessary for the purposes set out in this + Privacy Policy. We will retain and use Your Personal Data to the extent necessary to comply with our legal + obligations (for example, if we are required to retain your data to comply with applicable laws), resolve + disputes, and enforce our legal agreements and policies.</p> + <p>The Company will also retain Usage Data for internal analysis purposes. Usage Data is generally retained for a + shorter period of time, except when this data is used to strengthen the security or to improve the functionality + of Our Service, or We are legally obligated to retain this data for longer time periods.</p> + <h4>Transfer of Your Personal Data</h4> + <p>Your information, including Personal Data, is processed at the Company's operating offices and in any other + places where the parties involved in the processing are located. It means that this information may be + transferred to — and maintained on — computers located outside of Your state, province, country or other + governmental jurisdiction where the data protection laws may differ than those from Your jurisdiction.</p> + <p>Your consent to this Privacy Policy followed by Your submission of such information represents Your agreement to + that transfer.</p> + <p>The Company will take all steps reasonably necessary to ensure that Your data is treated securely and in + accordance with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or + a country unless there are adequate controls in place including the security of Your data and other personal + information.</p> + <h4>Delete Your Personal Data</h4> + <p>You have the right to delete or request that We assist in deleting the Personal Data that We have collected about + You.</p> + <p>Our Service may give You the ability to delete certain information about You from within the Service.</p> + <p>You may update, amend, or delete Your information at any time by signing in to Your Account, if you have one, and + visiting the account settings section that allows you to manage Your personal information. You may also contact + Us to request access to, correct, or delete any personal information that You have provided to Us.</p> + <p>Please note, however, that We may need to retain certain information when we have a legal obligation or lawful + basis to do so.</p> + <h4>Disclosure of Your Personal Data</h4> + <h5>Business Transactions</h5> + <p>If the Company is involved in a merger, acquisition or asset sale, Your Personal Data may be transferred. We will + provide notice before Your Personal Data is transferred and becomes subject to a different Privacy Policy.</p> + <h5>Law enforcement</h5> + <p>Under certain circumstances, the Company may be required to disclose Your Personal Data if required to do so by + law or in response to valid requests by public authorities (e.g. a court or a government agency).</p> + <h5>Other legal requirements</h5> + <p>The Company may disclose Your Personal Data in the good faith belief that such action is necessary to:</p> + <ul> + <li>Comply with a legal obligation</li> + <li>Protect and defend the rights or property of the Company</li> + <li>Prevent or investigate possible wrongdoing in connection with the Service</li> + <li>Protect the personal safety of Users of the Service or the public</li> + <li>Protect against legal liability</li> + </ul> + <h4>Security of Your Personal Data</h4> + <p>The security of Your Personal Data is important to Us, but remember that no method of transmission over the + Internet, or method of electronic storage is 100% secure. While We strive to use commercially acceptable means + to protect Your Personal Data, We cannot guarantee its absolute security.</p> + <h3>Children's Privacy</h3> + <p>Our Service does not address anyone under the age of 13. We do not knowingly collect personally identifiable + information from anyone under the age of 13. If You are a parent or guardian and You are aware that Your child + has provided Us with Personal Data, please contact Us. If We become aware that We have collected Personal Data + from anyone under the age of 13 without verification of parental consent, We take steps to remove that + information from Our servers.</p> + <p>If We need to rely on consent as a legal basis for processing Your information and Your country requires consent + from a parent, We may require Your parent's consent before We collect and use that information.</p> + <h3>Links to Other Websites</h3> + <p>Our Service may contain links to other websites that are not operated by Us. If You click on a third party link, + You will be directed to that third party's site. We strongly advise You to review the Privacy Policy of every + site You visit.</p> + <p>We have no control over and assume no responsibility for the content, privacy policies or practices of any third + party sites or services.</p> + <h3>Changes to this Privacy Policy</h3> + <p>We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy + Policy on this page.</p> + <p>We will let You know via email and/or a prominent notice on Our Service, prior to the change becoming effective + and update the "Last updated" date at the top of this Privacy Policy.</p> + <p>You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are + effective when they are posted on this page.</p> + <h3>Contact Us</h3> + <p>If you have any questions about this Privacy Policy, You can contact us:</p> + <ul> + <li> + <p>By email: privacy@carpentertutoring.com</p> + </li> + <li> + <p>By visiting this page on our website: <a href="https://carpentertutoring.com/policies" + rel="external nofollow noopener" target="_blank">https://carpentertutoring.com/policies</a></p> + </li> + </ul> +</section> + +{% endblock %}
\ No newline at end of file diff --git a/templates/post.html b/templates/post.html.j2 index fb8d28b..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 %} @@ -16,9 +16,9 @@ <h1>{{ post.get_title() }}</h1> </section> -<section class="quiet"> +<section> <article> - {{ post.get_article()|markdown }} + {{ post.get_article() | safe }} </article> </section> -{% endblock %} +{% endblock %}
\ No newline at end of file diff --git a/templates/posts.html b/templates/posts.html deleted file mode 100644 index 052cd42..0000000 --- a/templates/posts.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "base.html" %} - -{% block main %} -<section class="banner"> - <h1>Posts</h1> -</section> - -<section class="quiet"> - <p> - {% for post in posts %} - <h2><a href="/posts/{{ post.get_title()|e }}">{{ post.get_title() }}</a></h2> - {% endfor %} - </p> -<section> -{% endblock %} 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—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 |