add static landing page

This commit is contained in:
Yisroel Baum 2026-08-05 20:18:22 +03:00
parent 26a5baf72a
commit 37b7e4f619
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
20 changed files with 1564 additions and 11 deletions

View file

@ -1,7 +1,17 @@
# TIDE # TIDE
TIDE is the NixOS module for the Torah Im Derech Eretz forum. It deploys the TIDE is the website and NixOS module for the Torah Im Derech Eretz community.
forum with NixOS Discourse and configures its production Borg backup. It serves the static landing page at `torahimderecheretz.com`, deploys the
forum with NixOS Discourse, and configures its production Borg backup.
## Landing page
The landing page is a static HTML and CSS site in [`site`](./site). Build its
deployment package with:
```console
nix build .#landing-page
```
## NixOS module ## NixOS module
@ -21,8 +31,9 @@ services.tide = {
}; };
``` ```
The module owns the forum hostname, site identity, SMTP configuration, and The module owns the landing page and forum hostnames, site identity, SMTP
backup policy. The importing host owns secret provisioning. configuration, and backup policy. The importing host owns secret provisioning
and ACME account configuration.
See [RECOVERY.md](./RECOVERY.md) for the database and state restoration See [RECOVERY.md](./RECOVERY.md) for the database and state restoration
procedure. procedure.

View file

@ -11,6 +11,7 @@
let let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
landingPage = import ./nix/site.nix { inherit pkgs; };
in in
{ {
nixosModules.tide = import ./nix/module.nix; nixosModules.tide = import ./nix/module.nix;
@ -20,6 +21,8 @@
inherit nixpkgs self system; inherit nixpkgs self system;
}; };
packages.${system}.landing-page = landingPage;
formatter.${system} = pkgs.nixfmt-tree; formatter.${system} = pkgs.nixfmt-tree;
devShells.${system}.default = pkgs.mkShell { devShells.${system}.default = pkgs.mkShell {

View file

@ -6,6 +6,17 @@
}: }:
let let
cfg = config.services.tide; cfg = config.services.tide;
landingPage = import ./site.nix { inherit pkgs; };
contentSecurityPolicy = lib.concatStringsSep " " [
"default-src 'self';"
"base-uri 'self';"
"font-src 'self';"
"form-action 'self';"
"frame-ancestors 'none';"
"img-src 'self' data:;"
"object-src 'none';"
"style-src 'self';"
];
dumpCommand = lib.concatStringsSep " " [ dumpCommand = lib.concatStringsSep " " [
"${config.services.postgresql.package}/bin/pg_dump" "${config.services.postgresql.package}/bin/pg_dump"
"--format=custom" "--format=custom"
@ -32,6 +43,25 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts."torahimderecheretz.com" = {
enableACME = true;
forceSSL = true;
root = landingPage;
locations."/" = {
tryFiles = "$uri $uri/ =404";
extraConfig = ''
add_header Content-Security-Policy "${contentSecurityPolicy}" always;
add_header Permissions-Policy "camera=(), geolocation=(), microphone=()" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Content-Type-Options "nosniff" always;
'';
};
};
};
services.discourse = { services.discourse = {
enable = true; enable = true;
admin = { admin = {

18
nix/site.nix Normal file
View file

@ -0,0 +1,18 @@
{ pkgs }:
pkgs.stdenvNoCC.mkDerivation {
pname = "tide-landing-page";
version = "1.0.0";
src = ../site;
dontBuild = true;
installPhase = ''
runHook preInstall
mkdir -p "$out"
cp -R . "$out"
runHook postInstall
'';
}

View file

@ -25,8 +25,7 @@ let
}; };
evaluatedConfig = evaluatedSystem.config; evaluatedConfig = evaluatedSystem.config;
landingPage = self.packages.${system}.landing-page; landingPage = self.packages.${system}.landing-page;
landingVirtualHost = landingVirtualHost = evaluatedConfig.services.nginx.virtualHosts."torahimderecheretz.com";
evaluatedConfig.services.nginx.virtualHosts."torahimderecheretz.com";
discourseConfig = evaluatedConfig.services.discourse; discourseConfig = evaluatedConfig.services.discourse;
backupConfig = evaluatedConfig.services.borgbackup.jobs.discourse; backupConfig = evaluatedConfig.services.borgbackup.jobs.discourse;
backupService = evaluatedConfig.systemd.services.borgbackup-job-discourse; backupService = evaluatedConfig.systemd.services.borgbackup-job-discourse;
@ -37,10 +36,8 @@ assert discourseConfig.admin.email == "yisroel.d.baum@gmail.com";
assert discourseConfig.admin.fullName == "Yisroel Baum"; assert discourseConfig.admin.fullName == "Yisroel Baum";
assert discourseConfig.admin.username == "yisroeldbaum"; assert discourseConfig.admin.username == "yisroeldbaum";
assert discourseConfig.admin.passwordFile == "/run/secrets/tide-admin-password"; assert discourseConfig.admin.passwordFile == "/run/secrets/tide-admin-password";
assert discourseConfig.mail.notificationEmailAddress == assert discourseConfig.mail.notificationEmailAddress == "system@torahimderecheretz.com";
"system@torahimderecheretz.com"; assert discourseConfig.mail.contactEmailAddress == "system@torahimderecheretz.com";
assert discourseConfig.mail.contactEmailAddress ==
"system@torahimderecheretz.com";
assert discourseConfig.mail.outgoing.passwordFile == "/run/secrets/tide-mail-password"; assert discourseConfig.mail.outgoing.passwordFile == "/run/secrets/tide-mail-password";
assert discourseConfig.mail.outgoing.serverAddress == "in-v3.mailjet.com"; assert discourseConfig.mail.outgoing.serverAddress == "in-v3.mailjet.com";
assert discourseConfig.mail.outgoing.port == 587; assert discourseConfig.mail.outgoing.port == 587;
@ -48,7 +45,7 @@ assert discourseConfig.mail.outgoing.authentication == "login";
assert discourseConfig.siteSettings.required.title == "Torah Im Derech Eretz"; assert discourseConfig.siteSettings.required.title == "Torah Im Derech Eretz";
assert discourseConfig.secretKeyBaseFile == "/run/secrets/tide-secret-key-base"; assert discourseConfig.secretKeyBaseFile == "/run/secrets/tide-secret-key-base";
assert evaluatedConfig.services.nginx.enable; assert evaluatedConfig.services.nginx.enable;
assert landingVirtualHost.root == "${landingPage}"; assert landingVirtualHost.root == landingPage;
assert landingVirtualHost.enableACME; assert landingVirtualHost.enableACME;
assert landingVirtualHost.forceSSL; assert landingVirtualHost.forceSSL;
assert landingVirtualHost.locations."/".tryFiles == "$uri $uri/ =404"; assert landingVirtualHost.locations."/".tryFiles == "$uri $uri/ =404";
@ -68,6 +65,7 @@ pkgs.runCommand "tide-module-test" { } ''
test -f ${landingPage}/styles.css test -f ${landingPage}/styles.css
test -f ${landingPage}/robots.txt test -f ${landingPage}/robots.txt
test -f ${landingPage}/assets/rav-hirsch-1847.jpg test -f ${landingPage}/assets/rav-hirsch-1847.jpg
test -f ${landingPage}/assets/rav-hirsch-1847.webp
${pkgs.gnugrep}/bin/grep -F \ ${pkgs.gnugrep}/bin/grep -F \
"A Torah vision for the whole of life." \ "A Torah vision for the whole of life." \
${landingPage}/index.html ${landingPage}/index.html

View file

@ -0,0 +1,93 @@
Copyright 2012 The Libre Baskerville Project Authors (https://github.com/impallari/Libre-Baskerville) with Reserved Font Name Libre Baskerville.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View file

@ -0,0 +1,93 @@
Copyright 2022 The Noto Project Authors (https://github.com/notofonts/hebrew)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View file

@ -0,0 +1,93 @@
Copyright 2010-2020 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

View file

@ -0,0 +1,50 @@
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="1200"
height="630"
viewBox="0 0 1200 630"
>
<defs>
<clipPath id="portrait-clip">
<rect x="790" y="0" width="410" height="630"/>
</clipPath>
<linearGradient id="portrait-fade" x1="0" x2="1">
<stop offset="0" stop-color="#244a3d"/>
<stop offset="0.3" stop-color="#244a3d" stop-opacity="0.12"/>
<stop offset="1" stop-color="#244a3d" stop-opacity="0"/>
</linearGradient>
</defs>
<rect width="1200" height="630" fill="#f4f0e6"/>
<rect width="18" height="630" fill="#743d36"/>
<rect x="55" y="52" width="1090" height="526" fill="none" stroke="#ad8950"/>
<image
x="790"
y="0"
width="600"
height="630"
preserveAspectRatio="xMidYMid slice"
xlink:href="rav-hirsch-1847.jpg"
clip-path="url(#portrait-clip)"
/>
<rect x="790" width="180" height="630" fill="url(#portrait-fade)"/>
<text
x="96"
y="132"
fill="#743d36"
font-family="sans-serif"
font-size="24"
font-weight="600"
letter-spacing="3"
>TORAH IM DERECH ERETZ</text>
<line x1="96" y1="159" x2="216" y2="159" stroke="#ad8950" stroke-width="3"/>
<text x="96" y="260" fill="#192721" font-family="serif" font-size="64">
<tspan x="96" dy="0">A Torah vision</tspan>
<tspan x="96" dy="82">for the whole of life.</tspan>
</text>
<text x="96" y="474" fill="#244a3d" font-family="sans-serif" font-size="27">
The teachings of Rav Samson Raphael Hirsch
</text>
<circle cx="106" cy="534" r="10" fill="#ad8950"/>
<line x1="128" y1="534" x2="520" y2="534" stroke="#244a3d" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

12
site/favicon.svg Normal file
View file

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<rect width="64" height="64" rx="32" fill="#244a3d"/>
<path
d="M14 18c7 0 13 2 18 7 5-5 11-7 18-7v28c-7 0-13 2-18 7-5-5-11-7-18-7V18Z"
fill="none"
stroke="#f4f0e6"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="3"
/>
<path d="M32 25v28" stroke="#ad8950" stroke-width="3"/>
</svg>

After

Width:  |  Height:  |  Size: 387 B

290
site/index.html Normal file
View file

@ -0,0 +1,290 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Torah Im Derech Eretz</title>
<meta
name="description"
content="Discover and discuss Rav Samson Raphael Hirsch's vision of Torah for the whole of life."
>
<meta name="theme-color" content="#244a3d">
<link rel="canonical" href="https://torahimderecheretz.com/">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Torah Im Derech Eretz">
<meta property="og:title" content="A Torah vision for the whole of life">
<meta
property="og:description"
content="Explore Rav Samson Raphael Hirsch's enduring approach to Torah, work, education, culture, and community."
>
<meta property="og:url" content="https://torahimderecheretz.com/">
<meta
property="og:image"
content="https://torahimderecheretz.com/assets/social-preview.png"
>
<meta
property="og:image:alt"
content="Torah Im Derech Eretz: A Torah vision for the whole of life"
>
<meta name="twitter:card" content="summary_large_image">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link
rel="preload"
href="/assets/fonts/libre-baskerville-latin.woff2"
as="font"
type="font/woff2"
crossorigin
>
<link
rel="preload"
href="/assets/fonts/source-sans-3-latin.woff2"
as="font"
type="font/woff2"
crossorigin
>
<link
rel="preload"
href="/assets/rav-hirsch-1847.webp"
as="image"
type="image/webp"
>
<link rel="stylesheet" href="/styles.css">
</head>
<body id="top">
<a class="skip-link" href="#main-content">Skip to main content</a>
<header class="site-header">
<div class="container site-header__inner">
<a class="brand" href="#top" aria-label="Torah Im Derech Eretz home">
<span class="brand__seal" aria-hidden="true">
<svg viewBox="0 0 32 32" role="img">
<path d="M7 8.5c3.4 0 6.4 1 9 3.3 2.6-2.3 5.6-3.3 9-3.3v15c-3.5 0-6.5 1-9 3.2-2.5-2.2-5.5-3.2-9-3.2z"/>
<path d="M16 11.8v14.9"/>
</svg>
</span>
<span class="brand__name">Torah Im Derech Eretz</span>
</a>
<nav class="site-nav" aria-label="Primary navigation">
<ul class="site-nav__list">
<li><a href="#vision">The Vision</a></li>
<li><a href="#rav-hirsch">Rav Hirsch</a></li>
<li><a href="#community">Community</a></li>
</ul>
</nav>
<a
class="button button--small"
href="https://discourse.torahimderecheretz.com"
>
Join the Forum
<span aria-hidden="true"></span>
</a>
</div>
</header>
<main id="main-content">
<section class="hero" aria-labelledby="hero-title">
<div class="hero__ornament" aria-hidden="true">תורה</div>
<div class="container hero__grid">
<div class="hero__content">
<p class="eyebrow" lang="he" dir="rtl">תורה עם דרך ארץ</p>
<h1 id="hero-title">A Torah vision for the whole of life.</h1>
<p class="hero__lede">
Discover and discuss Rav Samson Raphael Hirschs enduring
approach to Torah, work, education, culture, and communal
responsibility.
</p>
<div class="hero__actions">
<a
class="button button--primary"
href="https://discourse.torahimderecheretz.com"
>
Join the Forum
<span aria-hidden="true"></span>
</a>
<a class="text-link" href="#vision">
Explore the vision
<span aria-hidden="true"></span>
</a>
</div>
<p class="hero__note">
A community devoted to learning, living, and sharing the
teachings of Rav Hirsch.
</p>
</div>
<figure class="portrait">
<div class="portrait__frame">
<picture>
<source
srcset="/assets/rav-hirsch-1847.webp"
type="image/webp"
>
<img
src="/assets/rav-hirsch-1847.jpg"
width="960"
height="1005"
alt="Lithographic portrait of Rav Samson Raphael Hirsch as a young man"
>
</picture>
<span class="portrait__dates">1808 · 1888</span>
</div>
<figcaption>Rav Samson Raphael Hirsch</figcaption>
</figure>
</div>
</section>
<section class="vision section" id="vision" aria-labelledby="vision-title">
<div class="container">
<div class="section-heading section-heading--split">
<div>
<p class="eyebrow">The Vision</p>
<h2 id="vision-title">One Torah. A whole life.</h2>
</div>
<p>
Torah Im Derech Eretz is not a division between sacred and
ordinary life. It is a way of allowing Torah to give direction
and purpose to every human pursuit.
</p>
</div>
<div class="principles">
<article class="principle">
<p class="principle__number" aria-hidden="true">01</p>
<div class="principle__rule" aria-hidden="true"></div>
<h3>Torah as the measure</h3>
<p>
Torah is not one compartment among many. Its wisdom and
obligations shape how we understand every part of life.
</p>
</article>
<article class="principle">
<p class="principle__number" aria-hidden="true">02</p>
<div class="principle__rule" aria-hidden="true"></div>
<h3>Engagement with Derech Eretz</h3>
<p>
Work, education, culture, and society become arenas for
responsible service of God and the fulfillment of our task.
</p>
</article>
<article class="principle">
<p class="principle__number" aria-hidden="true">03</p>
<div class="principle__rule" aria-hidden="true"></div>
<h3>A living community</h3>
<p>
Serious learning is carried into practice through thoughtful
conversation, shared resources, and respectful disagreement.
</p>
</article>
</div>
</div>
</section>
<section
class="hirsch section"
id="rav-hirsch"
aria-labelledby="hirsch-title"
>
<div class="container hirsch__grid">
<div class="hirsch__intro">
<p class="eyebrow">Rav Hirsch</p>
<h2 id="hirsch-title">Faithful, thoughtful, and fully alive.</h2>
</div>
<div class="hirsch__copy">
<p class="drop-cap">
Rav Samson Raphael Hirsch was a nineteenth-century rabbi,
commentator, educator, and communal leader. In an age of rapid
social change, he articulated a Judaism of unwavering Torah
commitment and serious engagement with the wider world.
</p>
<p>
Through works such as <cite>The Nineteen Letters</cite>,
<cite>Horeb</cite>, and his Torah commentary, Rav Hirsch taught
that every dimension of human life could be directed toward
<span lang="he-Latn">avodas Hashem</span>, the service of God.
</p>
</div>
<aside class="works" aria-label="Selected works by Rav Hirsch">
<p class="works__label">Selected works</p>
<ul>
<li>The Nineteen Letters</li>
<li>Horeb</li>
<li>Commentary on the Torah</li>
<li>Collected Writings</li>
</ul>
</aside>
</div>
</section>
<section
class="community section"
id="community"
aria-labelledby="community-title"
>
<div class="community__hebrew" aria-hidden="true">יחד</div>
<div class="container community__inner">
<p class="eyebrow eyebrow--light">The Community</p>
<h2 id="community-title">Study deeply. Ask honestly. Build together.</h2>
<p class="community__lede">
Join a thoughtful forum for discussing Rav Hirschs writings,
applying his ideas, sharing resources, and learning with others
who believe Torah speaks to the whole of life.
</p>
<div class="community__topics" aria-label="Forum topics">
<span>Source study</span>
<span>Ideas in practice</span>
<span>History and legacy</span>
</div>
<a
class="button button--light"
href="https://discourse.torahimderecheretz.com"
>
Join the Forum
<span aria-hidden="true"></span>
</a>
</div>
</section>
</main>
<footer class="site-footer">
<div class="container site-footer__main">
<div>
<a class="brand brand--footer" href="#top">
<span class="brand__seal" aria-hidden="true">
<svg viewBox="0 0 32 32" role="img">
<path d="M7 8.5c3.4 0 6.4 1 9 3.3 2.6-2.3 5.6-3.3 9-3.3v15c-3.5 0-6.5 1-9 3.2-2.5-2.2-5.5-3.2-9-3.2z"/>
<path d="M16 11.8v14.9"/>
</svg>
</span>
<span class="brand__name">Torah Im Derech Eretz</span>
</a>
<p class="site-footer__mission">
Learning, living, and sharing the teachings of Rav Samson Raphael
Hirsch.
</p>
</div>
<nav aria-label="Footer navigation">
<a href="#vision">The Vision</a>
<a href="#rav-hirsch">Rav Hirsch</a>
<a href="https://discourse.torahimderecheretz.com">Forum</a>
</nav>
</div>
<div class="container site-footer__legal">
<p>© Torah Im Derech Eretz</p>
<p>
Portrait: 1847 lithograph by Druck von Schier,
<a
href="https://commons.wikimedia.org/wiki/File:Druck_von_Schier._Samson_Raphael_Hirsch.1847.jpg"
>public domain</a>.
</p>
</div>
</footer>
</body>
</html>

4
site/robots.txt Normal file
View file

@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: https://torahimderecheretz.com/sitemap.xml

6
site/sitemap.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://torahimderecheretz.com/</loc>
</url>
</urlset>

852
site/styles.css Normal file
View file

@ -0,0 +1,852 @@
@font-face {
font-family: "Libre Baskerville";
font-style: normal;
font-weight: 400 700;
font-display: swap;
src: url("/assets/fonts/libre-baskerville-latin.woff2") format("woff2");
}
@font-face {
font-family: "Source Sans 3";
font-style: normal;
font-weight: 400 600;
font-display: swap;
src: url("/assets/fonts/source-sans-3-latin.woff2") format("woff2");
}
@font-face {
font-family: "Noto Serif Hebrew";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("/assets/fonts/noto-serif-hebrew.woff2") format("woff2");
}
:root {
--color-paper: #f4f0e6;
--color-paper-deep: #e9e1d1;
--color-ink: #192721;
--color-forest: #244a3d;
--color-forest-dark: #17352c;
--color-burgundy: #743d36;
--color-brass: #ad8950;
--color-white: #fff;
--font-display: "Libre Baskerville", Georgia, serif;
--font-body: "Source Sans 3", "Segoe UI", sans-serif;
--font-hebrew: "Noto Serif Hebrew", "Times New Roman", serif;
--shadow-soft: 0 1.5rem 4rem rgb(25 39 33 / 14%);
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
color-scheme: light;
scroll-behavior: smooth;
}
body {
margin: 0;
background: var(--color-paper);
color: var(--color-ink);
font-family: var(--font-body);
font-size: 1.125rem;
line-height: 1.65;
-webkit-font-smoothing: antialiased;
}
body::before {
position: fixed;
z-index: -1;
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140' viewBox='0 0 140 140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.025'/%3E%3C/svg%3E");
content: "";
pointer-events: none;
}
img,
svg {
display: block;
max-width: 100%;
}
a {
color: inherit;
}
p,
h1,
h2,
h3,
figure {
margin-top: 0;
}
h1,
h2,
h3 {
font-family: var(--font-display);
font-weight: 400;
line-height: 1.13;
text-wrap: balance;
}
h1 {
max-width: 12ch;
margin-bottom: 1.75rem;
font-size: clamp(3rem, 6.8vw, 6.35rem);
letter-spacing: -0.045em;
}
h2 {
margin-bottom: 1.5rem;
font-size: clamp(2.35rem, 4.5vw, 4.4rem);
letter-spacing: -0.035em;
}
h3 {
margin-bottom: 1rem;
font-size: clamp(1.35rem, 2vw, 1.65rem);
letter-spacing: -0.02em;
}
cite {
font-family: var(--font-display);
}
:focus-visible {
outline: 3px solid var(--color-burgundy);
outline-offset: 4px;
}
.container {
width: min(100% - 3rem, 72rem);
margin-inline: auto;
}
.section {
padding-block: clamp(5.5rem, 10vw, 9rem);
scroll-margin-top: 6rem;
}
.skip-link {
position: fixed;
z-index: 100;
top: 0.75rem;
left: 0.75rem;
padding: 0.75rem 1rem;
transform: translateY(-160%);
background: var(--color-white);
color: var(--color-ink);
font-weight: 600;
}
.skip-link:focus {
transform: translateY(0);
}
.site-header {
position: sticky;
z-index: 20;
top: 0;
border-bottom: 1px solid rgb(25 39 33 / 14%);
background: rgb(244 240 230 / 94%);
backdrop-filter: blur(12px);
}
.site-header__inner {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
min-height: 5.25rem;
gap: 2rem;
}
.brand {
display: inline-flex;
align-items: center;
gap: 0.8rem;
text-decoration: none;
}
.brand__seal {
display: grid;
width: 2.3rem;
height: 2.3rem;
flex: none;
place-items: center;
border: 1px solid var(--color-brass);
border-radius: 50%;
}
.brand__seal svg {
width: 1.4rem;
fill: none;
stroke: currentColor;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 1.4;
}
.brand__name {
max-width: 12rem;
font-family: var(--font-display);
font-size: 0.96rem;
font-weight: 700;
line-height: 1.25;
}
.site-nav__list {
display: flex;
justify-content: center;
margin: 0;
padding: 0;
gap: clamp(1.1rem, 2.5vw, 2.4rem);
list-style: none;
}
.site-nav a,
.site-footer nav a {
text-underline-offset: 0.35rem;
text-decoration-color: transparent;
text-decoration-thickness: 1px;
transition: text-decoration-color 160ms ease;
}
.site-nav a {
font-size: 0.92rem;
font-weight: 600;
letter-spacing: 0.02em;
text-decoration-line: underline;
}
.site-nav a:hover,
.site-footer nav a:hover {
text-decoration-color: var(--color-brass);
}
.button {
display: inline-flex;
min-height: 3.6rem;
align-items: center;
justify-content: center;
padding: 0.85rem 1.35rem;
gap: 0.7rem;
border: 1px solid currentColor;
border-radius: 0.15rem;
font-size: 0.98rem;
font-weight: 600;
line-height: 1;
text-decoration: none;
transition:
background-color 160ms ease,
color 160ms ease,
transform 160ms ease;
}
.button span {
font-size: 1.15em;
line-height: 0;
}
.button:hover {
transform: translateY(-2px);
}
.button--small {
min-height: 2.8rem;
padding: 0.7rem 1rem;
background: var(--color-forest);
color: var(--color-white);
font-size: 0.88rem;
}
.button--small:hover,
.button--primary:hover {
background: var(--color-forest-dark);
}
.button--primary {
background: var(--color-forest);
color: var(--color-white);
}
.button--light {
border-color: var(--color-paper);
background: var(--color-paper);
color: var(--color-forest-dark);
}
.button--light:hover {
background: var(--color-white);
}
.hero {
position: relative;
min-height: calc(100svh - 5.25rem);
overflow: hidden;
padding-block: clamp(4.5rem, 8vw, 7rem);
}
.hero::after {
position: absolute;
z-index: -1;
right: 0;
bottom: 0;
left: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent,
var(--color-brass) 25%,
var(--color-brass) 75%,
transparent
);
content: "";
opacity: 0.7;
}
.hero__ornament {
position: absolute;
z-index: -1;
top: 48%;
left: -0.08em;
transform: translateY(-50%);
color: rgb(36 74 61 / 3.5%);
font-family: var(--font-hebrew);
font-size: clamp(10rem, 31vw, 30rem);
font-weight: 600;
line-height: 1;
pointer-events: none;
}
.hero__grid {
display: grid;
grid-template-columns: minmax(0, 1.12fr) minmax(20rem, 0.88fr);
align-items: center;
gap: clamp(3rem, 7vw, 7rem);
}
.eyebrow {
display: flex;
align-items: center;
margin-bottom: 1.5rem;
gap: 0.8rem;
color: var(--color-burgundy);
font-size: 0.76rem;
font-weight: 600;
letter-spacing: 0.19em;
line-height: 1.3;
text-transform: uppercase;
}
.eyebrow::before {
width: 2.5rem;
height: 1px;
background: var(--color-brass);
content: "";
}
.hero .eyebrow {
font-family: var(--font-hebrew);
font-size: 1rem;
letter-spacing: 0.08em;
}
.hero__lede {
max-width: 37rem;
margin-bottom: 2rem;
font-size: clamp(1.2rem, 2.1vw, 1.45rem);
line-height: 1.6;
}
.hero__actions {
display: flex;
align-items: center;
margin-bottom: 2.3rem;
gap: 1.7rem;
}
.text-link {
display: inline-flex;
align-items: center;
gap: 0.65rem;
font-size: 0.96rem;
font-weight: 600;
text-decoration-color: var(--color-brass);
text-underline-offset: 0.35rem;
}
.hero__note {
max-width: 30rem;
margin-bottom: 0;
padding-left: 1rem;
border-left: 2px solid var(--color-brass);
color: rgb(25 39 33 / 72%);
font-size: 0.86rem;
line-height: 1.5;
}
.portrait {
width: min(100%, 29rem);
margin: 0 auto;
}
.portrait__frame {
position: relative;
padding: 0.65rem;
border: 1px solid var(--color-brass);
background: var(--color-paper-deep);
box-shadow: var(--shadow-soft);
}
.portrait__frame::before {
position: absolute;
z-index: -1;
inset: 1rem -1rem -1rem 1rem;
border: 1px solid rgb(116 61 54 / 38%);
content: "";
}
.portrait img {
width: 100%;
aspect-ratio: 0.955;
background: #d7cec1;
filter: sepia(0.12) contrast(1.04);
object-fit: cover;
}
.portrait__dates {
position: absolute;
right: 1.4rem;
bottom: 1.35rem;
padding: 0.45rem 0.65rem;
background: rgb(244 240 230 / 92%);
font-family: var(--font-display);
font-size: 0.72rem;
letter-spacing: 0.13em;
}
.portrait figcaption {
margin-top: 1.5rem;
font-family: var(--font-display);
font-size: 0.95rem;
text-align: center;
}
.vision {
background: rgb(255 255 255 / 32%);
}
.section-heading--split {
display: grid;
grid-template-columns: 1fr 0.75fr;
align-items: end;
margin-bottom: clamp(4rem, 7vw, 6.5rem);
gap: clamp(2rem, 8vw, 8rem);
}
.section-heading h2 {
max-width: 13ch;
margin-bottom: 0;
}
.section-heading > p {
max-width: 34rem;
margin-bottom: 0.55rem;
color: rgb(25 39 33 / 78%);
}
.principles {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: clamp(2rem, 4vw, 4rem);
}
.principle__number {
margin-bottom: 1rem;
color: var(--color-burgundy);
font-family: var(--font-display);
font-size: 0.9rem;
}
.principle__rule {
position: relative;
width: 100%;
height: 1px;
margin-bottom: 2rem;
background: rgb(25 39 33 / 25%);
}
.principle__rule::before {
position: absolute;
top: -3px;
left: 0;
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--color-brass);
content: "";
}
.principle p:last-child {
margin-bottom: 0;
color: rgb(25 39 33 / 76%);
font-size: 1rem;
}
.hirsch {
position: relative;
}
.hirsch::before {
position: absolute;
top: 0;
right: max(1.5rem, calc((100% - 72rem) / 2));
width: min(15rem, 25vw);
height: 0.4rem;
background: var(--color-burgundy);
content: "";
}
.hirsch__grid {
display: grid;
grid-template-columns: 0.9fr 1.1fr;
gap: clamp(3rem, 8vw, 8rem);
}
.hirsch__intro h2 {
max-width: 10ch;
}
.hirsch__copy {
max-width: 39rem;
}
.hirsch__copy p {
margin-bottom: 1.5rem;
}
.drop-cap::first-letter {
float: left;
margin: 0.15em 0.13em 0 0;
color: var(--color-burgundy);
font-family: var(--font-display);
font-size: 4.4rem;
line-height: 0.7;
}
.works {
grid-column: 2;
margin-top: 1.25rem;
padding-top: 2rem;
border-top: 1px solid var(--color-brass);
}
.works__label {
margin-bottom: 1rem;
color: var(--color-burgundy);
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.16em;
text-transform: uppercase;
}
.works ul {
display: flex;
flex-wrap: wrap;
margin: 0;
padding: 0;
gap: 0.4rem 1.8rem;
list-style: none;
}
.works li {
font-family: var(--font-display);
font-size: 0.95rem;
}
.works li::before {
margin-right: 0.55rem;
color: var(--color-brass);
content: "•";
}
.community {
position: relative;
overflow: hidden;
background: var(--color-forest);
color: var(--color-paper);
}
.community::before,
.community::after {
position: absolute;
width: 25rem;
height: 25rem;
border: 1px solid rgb(173 137 80 / 24%);
border-radius: 50%;
content: "";
}
.community::before {
top: -16rem;
left: -10rem;
}
.community::after {
right: -11rem;
bottom: -17rem;
}
.community__hebrew {
position: absolute;
top: 50%;
right: 0.03em;
transform: translateY(-50%);
color: rgb(244 240 230 / 4%);
font-family: var(--font-hebrew);
font-size: clamp(12rem, 31vw, 30rem);
font-weight: 600;
line-height: 1;
}
.community__inner {
position: relative;
z-index: 1;
max-width: 52rem;
margin-inline: auto;
text-align: center;
}
.eyebrow--light {
justify-content: center;
color: #e5c997;
}
.community h2 {
margin-inline: auto;
color: var(--color-white);
}
.community__lede {
max-width: 44rem;
margin: 0 auto 2.3rem;
color: rgb(244 240 230 / 83%);
font-size: 1.17rem;
}
.community__topics {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-bottom: 2.8rem;
gap: 0.65rem;
}
.community__topics span {
padding: 0.4rem 0.85rem;
border: 1px solid rgb(244 240 230 / 28%);
border-radius: 10rem;
color: rgb(244 240 230 / 78%);
font-size: 0.78rem;
letter-spacing: 0.04em;
}
.site-footer {
padding-block: 4.5rem 2rem;
background: var(--color-forest-dark);
color: var(--color-paper);
}
.site-footer__main {
display: flex;
align-items: start;
justify-content: space-between;
padding-bottom: 3.5rem;
gap: 3rem;
}
.brand--footer .brand__seal {
color: var(--color-paper);
}
.brand--footer .brand__name {
font-size: 1.05rem;
}
.site-footer__mission {
max-width: 28rem;
margin: 1.2rem 0 0;
color: rgb(244 240 230 / 66%);
font-size: 0.92rem;
}
.site-footer nav {
display: flex;
gap: 2rem;
}
.site-footer nav a {
font-size: 0.9rem;
text-decoration-line: underline;
}
.site-footer__legal {
display: flex;
justify-content: space-between;
padding-top: 1.5rem;
gap: 2rem;
border-top: 1px solid rgb(244 240 230 / 14%);
color: rgb(244 240 230 / 54%);
font-size: 0.72rem;
}
.site-footer__legal p {
margin: 0;
}
.site-footer__legal a {
text-underline-offset: 0.2rem;
}
@media (max-width: 56rem) {
.site-header__inner {
grid-template-columns: 1fr auto;
padding-top: 0.75rem;
gap: 0.6rem 1.25rem;
}
.site-nav {
grid-column: 1 / -1;
grid-row: 2;
border-top: 1px solid rgb(25 39 33 / 10%);
}
.site-nav__list {
justify-content: space-between;
padding-block: 0.6rem;
}
.hero {
min-height: auto;
}
.hero__grid {
grid-template-columns: 1fr;
}
.hero__content {
max-width: 45rem;
}
.portrait {
width: min(82%, 32rem);
}
.section {
scroll-margin-top: 8.5rem;
}
.section-heading--split,
.hirsch__grid {
grid-template-columns: 1fr;
gap: 2.25rem;
}
.principles {
gap: 2rem;
}
.works {
grid-column: 1;
}
}
@media (max-width: 42rem) {
body {
font-size: 1.05rem;
}
.container {
width: min(100% - 2rem, 72rem);
}
.site-header__inner {
column-gap: 0.75rem;
}
.brand__seal {
width: 2rem;
height: 2rem;
}
.brand__name {
max-width: 8rem;
font-size: 0.78rem;
}
.button--small {
min-height: 2.5rem;
padding: 0.65rem 0.8rem;
font-size: 0.78rem;
}
.site-nav a {
font-size: 0.78rem;
}
.hero {
padding-block: 3.75rem 5.5rem;
}
.hero__actions {
align-items: stretch;
flex-direction: column;
gap: 1.2rem;
}
.text-link {
justify-content: center;
}
.portrait {
width: calc(100% - 1rem);
}
.principles {
grid-template-columns: 1fr;
gap: 3rem;
}
.principle__rule {
margin-bottom: 1.4rem;
}
.site-footer__main,
.site-footer__legal {
align-items: flex-start;
flex-direction: column;
}
.site-footer nav {
flex-wrap: wrap;
gap: 1rem 1.5rem;
}
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
*,
*::before,
*::after {
scroll-behavior: auto !important;
transition-duration: 0.01ms !important;
}
}