diff --git a/Dockerfile b/Dockerfile
index c50d268f..60b16eac 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -31,10 +31,9 @@ ENV PATH=${POETRY_HOME}/bin:$PATH \
PORT=8000
RUN env
-# Install litestream (https://litestream.io/install/debian/)
-ARG PLATFORM=amd64
-RUN wget https://github.com/benbjohnson/litestream/releases/download/v0.3.9/litestream-v0.3.9-linux-$PLATFORM.deb
-RUN dpkg -i litestream-v0.3.9-linux-$PLATFORM.deb
+# Install litestream
+COPY ./scripts/install-litestream.sh ./scripts/
+RUN ./scripts/install-litestream.sh
# Install poetry
RUN curl -sSL https://install.python-poetry.org | python3 -
diff --git a/README.md b/README.md
index 431a913b..39bb6af6 100644
--- a/README.md
+++ b/README.md
@@ -134,11 +134,11 @@ Once your app is working, and you have TLS in place, you also configure:
This project is using SQLite as it's database -- even in production 😱.
Using SQLite is often discouraged to be used in production.
-Those concerns a usually based on the abilitiy to handle multiple writes and how to backup the database.
+Those concerns a usually based on the ability to handle multiple writes and how to backup the database.
For container deployments on a platform as a service (such as Heroku) there is also the problem of persisting the database between container restarts.
The write ability is not really an issue for this application.
-Since this app is mainly a content site with few editors working simulaneously (if ever) it is much more read-heavy than write-heavy.
+Since this app is mainly a content site with few editors working simultaneously (if ever), it is much more read-heavy than write-heavy.
Reads are easy for SQLite to handle.
The persistence problem does apply to this app though.
diff --git a/docker-compose.yaml b/docker-compose.yaml
index 2ddf9074..5d0c8ea0 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -3,8 +3,6 @@ services:
build:
context: .
target: backend-development
- args:
- - PLATFORM=arm64
command: ["tail", "-f", "/dev/null"]
env_file:
- .env
diff --git a/lpld/core/blocks.py b/lpld/core/blocks.py
index 09ff364a..5871c72b 100644
--- a/lpld/core/blocks.py
+++ b/lpld/core/blocks.py
@@ -1,5 +1,6 @@
from wagtail import blocks
from wagtail.admin import panels
+from wagtail.templatetags import wagtailcore_tags
class HeadingBlock(blocks.StructBlock):
@@ -8,9 +9,15 @@ class HeadingBlock(blocks.StructBlock):
panels = [panels.FieldPanel("text", classname="full")]
class Meta:
- template = "atoms/heading/heading-block.html"
+ template = "atoms/heading/heading.html"
icon = "title"
+ def get_context(self, value, parent_context=None):
+ return {
+ "level": 2,
+ "children": value.get("text"),
+ }
+
class SubheadingBlock(blocks.StructBlock):
text = blocks.CharBlock(required=True)
@@ -18,5 +25,103 @@ class SubheadingBlock(blocks.StructBlock):
panels = [panels.FieldPanel("text")]
class Meta:
- template = "atoms/heading/subheading-block.html"
+ template = "atoms/heading/heading.html"
icon = "title"
+
+ def get_context(self, value, parent_context=None):
+ return {
+ "level": 3,
+ "children": value.get("text"),
+ }
+
+
+class PageLinkBlock(blocks.StructBlock):
+ page = blocks.PageChooserBlock(required=True)
+ text = blocks.CharBlock(
+ required=False,
+ help_text="Text for the link. Defaults to page title.",
+ )
+
+ class Meta:
+ icon = "doc-full"
+ template = "atoms/link/link.html"
+
+ def get_context(self, value, parent_context=None):
+ page = value.get("page")
+ text = value.get("text")
+ return {
+ "text": text or page.title,
+ "href": page.get_url(),
+ }
+
+
+class LinkStream(blocks.StreamBlock):
+ """
+ Stream of links.
+
+ Each item should return context objects containing the keys `"text"` and `"href"`
+ from their `get_context` method.
+ """
+
+ page_link = PageLinkBlock()
+
+ class Meta:
+ icon = "list-ul"
+ template = "molecules/link-listing/link-listing.html"
+ min_num = 1
+
+ def get_context(self, value, parent_context=None):
+ links = [bb.block.get_context(bb.value) for bb in value]
+ return {"links": links}
+
+
+class LinkBlock(LinkStream):
+ """
+ Link stream with max 1 item.
+
+ Can be used as a flexible link block.
+ """
+
+ class Meta:
+ icon = "link"
+ template = "atoms/link/link.html"
+ min_num = 1
+ max_num = 1
+
+ def get_context(self, value, parent_context=None):
+ bound_block = value[0]
+ return bound_block.block.get_context(bound_block.value)
+
+
+class SimpleProseRichtext(blocks.RichTextBlock):
+ def __init__(self, *args, **kwargs):
+ if "features" not in kwargs:
+ kwargs["features"] = ["link", "bold", "italics"]
+ super().__init__(*args, **kwargs)
+
+ class Meta:
+ template = "organisms/prose/prose.html"
+
+ def get_context(self, value, parent_context=None) -> dict[str, str]:
+ return {"children": wagtailcore_tags.richtext(value)}
+
+
+class SectionBlock(blocks.StructBlock):
+ heading = HeadingBlock()
+ body = blocks.StreamBlock(
+ local_blocks=[
+ ("paragraph", SimpleProseRichtext()),
+ ("link_list", LinkStream()),
+ ],
+ min_rum=1,
+ required=False,
+ )
+
+ panels = [
+ panels.FieldPanel("heading"),
+ panels.FieldPanel("body"),
+ ]
+
+ class Meta:
+ template = "molecules/section/section-block.html"
+ icon = "bars"
diff --git a/lpld/core/models.py b/lpld/core/models.py
index 3bb6c5a1..863df33c 100644
--- a/lpld/core/models.py
+++ b/lpld/core/models.py
@@ -4,8 +4,6 @@
from wagtail import models as wagtail_models
from wagtail.admin import panels
-from lpld.navigation import utils as nav_utils
-
class BasePage(wagtail_models.Page):
class Meta(wagtail_models.Page.Meta):
@@ -15,10 +13,22 @@ class Meta(wagtail_models.Page.Meta):
def title_tag_content(self):
return self.get_title_tag_content()
- def get_title_tag_content(self):
- title_text = self.seo_title or self.title
- title_text = f"{ title_text } · lpld.io"
- return title_text
+ def get_title_tag_content(self) -> str:
+ parts = self.get_title_tag_parts()
+ sep = self.get_title_separator()
+ return sep.join(parts)
+
+ def get_title_tag_parts(self) -> list[str]:
+ title = self.seo_title or self.title
+ last = self.get_title_tag_last_part()
+ return [title, last]
+
+ def get_title_tag_last_part(self) -> str:
+ """Return the last part for the title tag."""
+ return "lpld.io"
+
+ def get_title_separator(self) -> str:
+ return " · "
@func_utils.cached_property
def meta_description(self):
@@ -27,13 +37,6 @@ def meta_description(self):
def get_meta_description(self):
return self.search_description or ""
- def get_context(self, request):
- context = super().get_context(request)
- context["primary_navigation_links"] = nav_utils.get_primary_navigation_links(
- request
- )
- return context
-
class AbstractLink(models.Model):
page = models.ForeignKey(
diff --git a/lpld/home/migrations/0004_homepage_body.py b/lpld/home/migrations/0004_homepage_body.py
new file mode 100644
index 00000000..cee2b6f4
--- /dev/null
+++ b/lpld/home/migrations/0004_homepage_body.py
@@ -0,0 +1,43 @@
+# Generated by Django 4.1.13 on 2024-03-09 00:37
+
+from django.db import migrations
+
+import wagtail.blocks
+import wagtail.fields
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("home", "0003_homepage_profile_image"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="homepage",
+ name="body",
+ field=wagtail.fields.StreamField(
+ [
+ (
+ "section",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "heading",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "text",
+ wagtail.blocks.CharBlock(required=True),
+ )
+ ]
+ ),
+ )
+ ]
+ ),
+ )
+ ],
+ blank=True,
+ use_json_field=True,
+ ),
+ ),
+ ]
diff --git a/lpld/home/migrations/0005_homepage_subtitle_alter_homepage_body.py b/lpld/home/migrations/0005_homepage_subtitle_alter_homepage_body.py
new file mode 100644
index 00000000..69e49b2e
--- /dev/null
+++ b/lpld/home/migrations/0005_homepage_subtitle_alter_homepage_body.py
@@ -0,0 +1,90 @@
+# Generated by Django 4.1.13 on 2024-07-07 23:51
+
+from django.db import migrations, models
+
+import wagtail.blocks
+import wagtail.fields
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("home", "0004_homepage_body"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="homepage",
+ name="subtitle",
+ field=models.CharField(blank=True, max_length=50),
+ ),
+ migrations.AlterField(
+ model_name="homepage",
+ name="body",
+ field=wagtail.fields.StreamField(
+ [
+ (
+ "section",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "heading",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "text",
+ wagtail.blocks.CharBlock(required=True),
+ )
+ ]
+ ),
+ ),
+ (
+ "body",
+ wagtail.blocks.StreamBlock(
+ [
+ (
+ "paragraph",
+ wagtail.blocks.RichTextBlock(
+ features=["link", "bold", "italics"]
+ ),
+ ),
+ (
+ "link_list",
+ wagtail.blocks.StreamBlock(
+ [
+ (
+ "page_link",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "page",
+ wagtail.blocks.PageChooserBlock(
+ required=True
+ ),
+ ),
+ (
+ "text",
+ wagtail.blocks.CharBlock(
+ help_text="Text for the link. Defaults to page title.",
+ required=False,
+ ),
+ ),
+ ]
+ ),
+ )
+ ]
+ ),
+ ),
+ ],
+ min_rum=1,
+ required=False,
+ ),
+ ),
+ ]
+ ),
+ )
+ ],
+ blank=True,
+ use_json_field=True,
+ ),
+ ),
+ ]
diff --git a/lpld/home/migrations/0006_update_paragraph_block.py b/lpld/home/migrations/0006_update_paragraph_block.py
new file mode 100644
index 00000000..da79ec65
--- /dev/null
+++ b/lpld/home/migrations/0006_update_paragraph_block.py
@@ -0,0 +1,85 @@
+# Generated by Django 4.1.13 on 2024-07-12 03:38
+
+from django.db import migrations
+
+import wagtail.blocks
+import wagtail.fields
+
+import lpld.core.blocks
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("home", "0005_homepage_subtitle_alter_homepage_body"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="homepage",
+ name="body",
+ field=wagtail.fields.StreamField(
+ [
+ (
+ "section",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "heading",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "text",
+ wagtail.blocks.CharBlock(required=True),
+ )
+ ]
+ ),
+ ),
+ (
+ "body",
+ wagtail.blocks.StreamBlock(
+ [
+ (
+ "paragraph",
+ lpld.core.blocks.SimpleProseRichtext(),
+ ),
+ (
+ "link_list",
+ wagtail.blocks.StreamBlock(
+ [
+ (
+ "page_link",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "page",
+ wagtail.blocks.PageChooserBlock(
+ required=True
+ ),
+ ),
+ (
+ "text",
+ wagtail.blocks.CharBlock(
+ help_text="Text for the link. Defaults to page title.",
+ required=False,
+ ),
+ ),
+ ]
+ ),
+ )
+ ]
+ ),
+ ),
+ ],
+ min_rum=1,
+ required=False,
+ ),
+ ),
+ ]
+ ),
+ )
+ ],
+ blank=True,
+ use_json_field=True,
+ ),
+ ),
+ ]
diff --git a/lpld/home/models.py b/lpld/home/models.py
index bfa1b0a5..e85b107f 100644
--- a/lpld/home/models.py
+++ b/lpld/home/models.py
@@ -1,4 +1,3 @@
-from django.apps import apps
from django.db import models
from django.utils import html as html_utils
@@ -6,6 +5,7 @@
from wagtail import images as wagtail_images
from wagtail.admin import panels
+from lpld.core import blocks as core_blocks
from lpld.core import models as core_models
@@ -15,6 +15,11 @@ class HomePage(core_models.BasePage):
max_count = 1
template = "pages/home/home.html"
+ subtitle = models.CharField(
+ max_length=50,
+ blank=True,
+ null=False,
+ )
introduction = fields.RichTextField(features=["link"], null=True, blank=True)
profile_image = models.ForeignKey(
wagtail_images.get_image_model_string(),
@@ -22,19 +27,24 @@ class HomePage(core_models.BasePage):
blank=True,
on_delete=models.SET_NULL,
)
+ body = fields.StreamField(
+ block_types=[
+ ("section", core_blocks.SectionBlock()),
+ ],
+ null=False,
+ blank=True,
+ use_json_field=True,
+ )
content_panels = core_models.BasePage.content_panels + [
+ panels.FieldPanel("subtitle"),
panels.FieldPanel("introduction"),
panels.FieldPanel("profile_image"),
+ panels.FieldPanel("body"),
]
- def get_context(self, request):
- context = super().get_context(request)
-
- ProjectPage = apps.get_model("projects", "ProjectPage")
- context["projects"] = ProjectPage.objects.all()
-
- return context
+ def get_title_tag_parts(self) -> list[str]:
+ return [self.title, self.subtitle, self.get_title_tag_last_part()]
def get_meta_description(self):
return self.search_description or self.get_introduction_without_tags() or ""
diff --git a/lpld/index/migrations/0002_indexpage_introduction.py b/lpld/index/migrations/0002_indexpage_introduction.py
new file mode 100644
index 00000000..25d4c1a7
--- /dev/null
+++ b/lpld/index/migrations/0002_indexpage_introduction.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.1.13 on 2024-07-18 03:57
+
+from django.db import migrations
+
+import wagtail.fields
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("index", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="indexpage",
+ name="introduction",
+ field=wagtail.fields.RichTextField(blank=True, max_length=500),
+ ),
+ ]
diff --git a/lpld/index/models.py b/lpld/index/models.py
index 55f023d2..92e4846c 100644
--- a/lpld/index/models.py
+++ b/lpld/index/models.py
@@ -1,12 +1,21 @@
from typing import Any
+from wagtail import fields as wagtail_fields
+from wagtail.admin import panels
+
from lpld.core import models as core_models
class IndexPage(core_models.BasePage):
template = "pages/index/index-page.html"
parent_page_types = ["home.HomePage"]
- subpage_types = ["articles.ArticlePage"]
+ subpage_types = ["articles.ArticlePage", "projects.ProjectPage"]
+
+ introduction = wagtail_fields.RichTextField(max_length=500, null=False, blank=True)
+
+ content_panels = tuple(core_models.BasePage.content_panels) + (
+ panels.FieldPanel("introduction"),
+ )
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
@@ -18,8 +27,8 @@ def get_index_entries(self) -> tuple[dict[str, Any], ...]:
for child in self.get_children().live().public():
index_entries.append(
{
- "title": child.title,
- "url": child.get_url(),
+ "text": child.title,
+ "href": child.get_url(),
}
)
return tuple(index_entries)
diff --git a/lpld/navigation/utils.py b/lpld/navigation/utils.py
index b02febda..56979f50 100644
--- a/lpld/navigation/utils.py
+++ b/lpld/navigation/utils.py
@@ -13,10 +13,4 @@ def get_primary_navigation_links(request):
PrimaryNavigationSetting = apps.get_model("navigation.PrimaryNavigationSetting")
links.extend(list(PrimaryNavigationSetting.for_request(request).links.all()))
- links.extend(
- [
- Link(text="Projects", href="/#projects"),
- Link(text="Contact", href="#contact"),
- ]
- )
return links
diff --git a/lpld/projects/models.py b/lpld/projects/models.py
index 9810db40..54bb179e 100644
--- a/lpld/projects/models.py
+++ b/lpld/projects/models.py
@@ -11,7 +11,7 @@
class ProjectPage(core_models.BasePage):
- parent_page_types = ["home.HomePage"]
+ parent_page_types = ["home.HomePage", "index.IndexPage"]
template = "pages/project-page/project-page.html"
image = models.ForeignKey(
diff --git a/lpld/static/public/fonts/inter/Inter-Black.woff2 b/lpld/static/public/fonts/inter/Inter-Black.woff2
new file mode 100644
index 00000000..18b35db7
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-Black.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-BlackItalic.woff2 b/lpld/static/public/fonts/inter/Inter-BlackItalic.woff2
new file mode 100644
index 00000000..02c9d8ec
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-BlackItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-Bold.woff2 b/lpld/static/public/fonts/inter/Inter-Bold.woff2
new file mode 100644
index 00000000..0f1b1576
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-Bold.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-BoldItalic.woff2 b/lpld/static/public/fonts/inter/Inter-BoldItalic.woff2
new file mode 100644
index 00000000..bc50f24c
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-BoldItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-ExtraBold.woff2 b/lpld/static/public/fonts/inter/Inter-ExtraBold.woff2
new file mode 100644
index 00000000..b1133688
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-ExtraBold.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-ExtraBoldItalic.woff2 b/lpld/static/public/fonts/inter/Inter-ExtraBoldItalic.woff2
new file mode 100644
index 00000000..a5b76ca8
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-ExtraBoldItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-ExtraLight.woff2 b/lpld/static/public/fonts/inter/Inter-ExtraLight.woff2
new file mode 100644
index 00000000..1d77ae8d
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-ExtraLight.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-ExtraLightItalic.woff2 b/lpld/static/public/fonts/inter/Inter-ExtraLightItalic.woff2
new file mode 100644
index 00000000..8c684920
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-ExtraLightItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-Italic.woff2 b/lpld/static/public/fonts/inter/Inter-Italic.woff2
new file mode 100644
index 00000000..4c24ce28
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-Italic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-Light.woff2 b/lpld/static/public/fonts/inter/Inter-Light.woff2
new file mode 100644
index 00000000..dbe61437
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-Light.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-LightItalic.woff2 b/lpld/static/public/fonts/inter/Inter-LightItalic.woff2
new file mode 100644
index 00000000..a40d0421
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-LightItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-Medium.woff2 b/lpld/static/public/fonts/inter/Inter-Medium.woff2
new file mode 100644
index 00000000..0fd2ee73
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-Medium.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-MediumItalic.woff2 b/lpld/static/public/fonts/inter/Inter-MediumItalic.woff2
new file mode 100644
index 00000000..96767155
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-MediumItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-Regular.woff2 b/lpld/static/public/fonts/inter/Inter-Regular.woff2
new file mode 100644
index 00000000..b8699af2
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-Regular.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-SemiBold.woff2 b/lpld/static/public/fonts/inter/Inter-SemiBold.woff2
new file mode 100644
index 00000000..95c48b18
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-SemiBold.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-SemiBoldItalic.woff2 b/lpld/static/public/fonts/inter/Inter-SemiBoldItalic.woff2
new file mode 100644
index 00000000..ddfe19e8
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-SemiBoldItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-Thin.woff2 b/lpld/static/public/fonts/inter/Inter-Thin.woff2
new file mode 100644
index 00000000..07909608
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-Thin.woff2 differ
diff --git a/lpld/static/public/fonts/inter/Inter-ThinItalic.woff2 b/lpld/static/public/fonts/inter/Inter-ThinItalic.woff2
new file mode 100644
index 00000000..a7bf2138
Binary files /dev/null and b/lpld/static/public/fonts/inter/Inter-ThinItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-Black.woff2 b/lpld/static/public/fonts/inter/InterDisplay-Black.woff2
new file mode 100644
index 00000000..8138123c
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-Black.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-BlackItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-BlackItalic.woff2
new file mode 100644
index 00000000..735ba21f
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-BlackItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-Bold.woff2 b/lpld/static/public/fonts/inter/InterDisplay-Bold.woff2
new file mode 100644
index 00000000..11c67196
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-Bold.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-BoldItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-BoldItalic.woff2
new file mode 100644
index 00000000..5b6a1fb0
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-BoldItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-ExtraBold.woff2 b/lpld/static/public/fonts/inter/InterDisplay-ExtraBold.woff2
new file mode 100644
index 00000000..9058e986
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-ExtraBold.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-ExtraBoldItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-ExtraBoldItalic.woff2
new file mode 100644
index 00000000..4cd61c06
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-ExtraBoldItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-ExtraLight.woff2 b/lpld/static/public/fonts/inter/InterDisplay-ExtraLight.woff2
new file mode 100644
index 00000000..8621b299
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-ExtraLight.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-ExtraLightItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-ExtraLightItalic.woff2
new file mode 100644
index 00000000..689c8d9c
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-ExtraLightItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-Italic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-Italic.woff2
new file mode 100644
index 00000000..11f20bc8
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-Italic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-Light.woff2 b/lpld/static/public/fonts/inter/InterDisplay-Light.woff2
new file mode 100644
index 00000000..446301c3
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-Light.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-LightItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-LightItalic.woff2
new file mode 100644
index 00000000..f6881961
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-LightItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-Medium.woff2 b/lpld/static/public/fonts/inter/InterDisplay-Medium.woff2
new file mode 100644
index 00000000..29160b2c
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-Medium.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-MediumItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-MediumItalic.woff2
new file mode 100644
index 00000000..ef1bcbe3
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-MediumItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-Regular.woff2 b/lpld/static/public/fonts/inter/InterDisplay-Regular.woff2
new file mode 100644
index 00000000..a6c04f68
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-Regular.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-SemiBold.woff2 b/lpld/static/public/fonts/inter/InterDisplay-SemiBold.woff2
new file mode 100644
index 00000000..2b4db239
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-SemiBold.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-SemiBoldItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-SemiBoldItalic.woff2
new file mode 100644
index 00000000..59091db3
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-SemiBoldItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-Thin.woff2 b/lpld/static/public/fonts/inter/InterDisplay-Thin.woff2
new file mode 100644
index 00000000..dc0b9486
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-Thin.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterDisplay-ThinItalic.woff2 b/lpld/static/public/fonts/inter/InterDisplay-ThinItalic.woff2
new file mode 100644
index 00000000..96439c0c
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterDisplay-ThinItalic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterVariable-Italic.woff2 b/lpld/static/public/fonts/inter/InterVariable-Italic.woff2
new file mode 100644
index 00000000..f22ec255
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterVariable-Italic.woff2 differ
diff --git a/lpld/static/public/fonts/inter/InterVariable.woff2 b/lpld/static/public/fonts/inter/InterVariable.woff2
new file mode 100644
index 00000000..22a12b04
Binary files /dev/null and b/lpld/static/public/fonts/inter/InterVariable.woff2 differ
diff --git a/lpld/static/public/fonts/inter/inter.css b/lpld/static/public/fonts/inter/inter.css
new file mode 100644
index 00000000..413e1976
--- /dev/null
+++ b/lpld/static/public/fonts/inter/inter.css
@@ -0,0 +1,57 @@
+/* Variable fonts usage:
+:root { font-family: "Inter", sans-serif; }
+@supports (font-variation-settings: normal) {
+ :root { font-family: "InterVariable", sans-serif; font-optical-sizing: auto; }
+} */
+@font-face {
+ font-family: InterVariable;
+ font-style: normal;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url("InterVariable.woff2") format("woff2");
+}
+@font-face {
+ font-family: InterVariable;
+ font-style: italic;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url("InterVariable-Italic.woff2") format("woff2");
+}
+
+/* static fonts */
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 100; font-display: swap; src: url("Inter-Thin.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 100; font-display: swap; src: url("Inter-ThinItalic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 200; font-display: swap; src: url("Inter-ExtraLight.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 200; font-display: swap; src: url("Inter-ExtraLightItalic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 300; font-display: swap; src: url("Inter-Light.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 300; font-display: swap; src: url("Inter-LightItalic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; src: url("Inter-Regular.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 400; font-display: swap; src: url("Inter-Italic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap; src: url("Inter-Medium.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 500; font-display: swap; src: url("Inter-MediumItalic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap; src: url("Inter-SemiBold.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 600; font-display: swap; src: url("Inter-SemiBoldItalic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap; src: url("Inter-Bold.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 700; font-display: swap; src: url("Inter-BoldItalic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 800; font-display: swap; src: url("Inter-ExtraBold.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 800; font-display: swap; src: url("Inter-ExtraBoldItalic.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: normal; font-weight: 900; font-display: swap; src: url("Inter-Black.woff2") format("woff2"); }
+@font-face { font-family: "Inter"; font-style: italic; font-weight: 900; font-display: swap; src: url("Inter-BlackItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 100; font-display: swap; src: url("InterDisplay-Thin.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 100; font-display: swap; src: url("InterDisplay-ThinItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 200; font-display: swap; src: url("InterDisplay-ExtraLight.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 200; font-display: swap; src: url("InterDisplay-ExtraLightItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 300; font-display: swap; src: url("InterDisplay-Light.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 300; font-display: swap; src: url("InterDisplay-LightItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 400; font-display: swap; src: url("InterDisplay-Regular.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 400; font-display: swap; src: url("InterDisplay-Italic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 500; font-display: swap; src: url("InterDisplay-Medium.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 500; font-display: swap; src: url("InterDisplay-MediumItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 600; font-display: swap; src: url("InterDisplay-SemiBold.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 600; font-display: swap; src: url("InterDisplay-SemiBoldItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 700; font-display: swap; src: url("InterDisplay-Bold.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 700; font-display: swap; src: url("InterDisplay-BoldItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 800; font-display: swap; src: url("InterDisplay-ExtraBold.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 800; font-display: swap; src: url("InterDisplay-ExtraBoldItalic.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 900; font-display: swap; src: url("InterDisplay-Black.woff2") format("woff2"); }
+@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 900; font-display: swap; src: url("InterDisplay-BlackItalic.woff2") format("woff2"); }
diff --git a/lpld/static/src/style.css b/lpld/static/src/style.css
index 90f73828..d7276d8d 100644
--- a/lpld/static/src/style.css
+++ b/lpld/static/src/style.css
@@ -2,25 +2,30 @@
@tailwind components;
@tailwind utilities;
-@layer components {
- .heading-lg {
- @apply font-bold text-neutral-700 text-4xl sm:text-5xl xl:text-6xl
- }
- .heading-md {
- @apply font-bold text-neutral-700 text-3xl sm:text-4xl xl:text-5xl
+@layer base {
+ :root {
+ @apply font-sans;
}
+ @supports (font-variation-settings: normal) {
+ :root {
+ @apply font-sans-var;
+ font-optical-sizing: auto;
+ }
+ }
+}
- .heading-sm {
- @apply font-bold text-neutral-700 text-2xl sm:text-3xl xl:text-4xl
+@layer components {
+ .link {
+ @apply font-medium text-neutral-500 underline underline-offset-[0.1em] decoration-1 hover:decoration-2 hover:text-neutral-800 active:text-neutral-900
}
- .heading-xs {
- @apply font-bold text-neutral-700 text-xl sm:text-2xl xl:text-3xl
+ .heading {
+ @apply font-bold text-neutral-600 tracking-tight
}
- .link {
- @apply text-neutral-500 underline underline-offset-2 decoration-1 hover:decoration-2 hover:text-neutral-800 active:text-neutral-900
+ h1, h2, h3, h4, h5, h6 {
+ @apply heading
}
}
@@ -29,7 +34,7 @@
Anchor links (in headings) in prose blocks should not get the prose link style, but keep the heading style.
This needs to be defined outside of a layer so it does not get tree-shaken, because the class is only used in the Markdown config.
*/
+ @apply font-bold;
color: inherit;
text-decoration: inherit;
- font-weight: inherit;
}
diff --git a/lpld/templates/atoms/chevron-link/chevron-link.html b/lpld/templates/atoms/chevron-link/chevron-link.html
new file mode 100644
index 00000000..e15ec0ba
--- /dev/null
+++ b/lpld/templates/atoms/chevron-link/chevron-link.html
@@ -0,0 +1,16 @@
+{% load slippers heroicons lpldutils %}
+{% spaceless %}
+
+ {% for word in text|split %}
+ {% if not forloop.last %}
+ {{ word }}
+ {% else %}
+ {# Span wrapper to avoid line-break between icon and last word. #}
+
+ {{ word }}
+ {% heroicon_mini "chevron-right" class="transition ease-linear group-hover:translate-x-0.5 delay-[10] duration-[10]" %}
+
+ {% endif %}
+ {% endfor %}
+
+{% endspaceless %}
diff --git a/lpld/templates/atoms/chevron-link/chevron-link.yaml b/lpld/templates/atoms/chevron-link/chevron-link.yaml
new file mode 100644
index 00000000..d675a445
--- /dev/null
+++ b/lpld/templates/atoms/chevron-link/chevron-link.yaml
@@ -0,0 +1,3 @@
+context:
+ text: 'Listing link title'
+ href: 'https://www.example.com'
diff --git a/lpld/templates/atoms/heading/heading-block.html b/lpld/templates/atoms/heading/heading-block.html
deleted file mode 100644
index 92859f8b..00000000
--- a/lpld/templates/atoms/heading/heading-block.html
+++ /dev/null
@@ -1,2 +0,0 @@
-{% load slippers %}
-{% #heading level="2" size="md" %}{{ value.text }}{% /heading %}
diff --git a/lpld/templates/atoms/heading/heading-block.yaml b/lpld/templates/atoms/heading/heading-block.yaml
deleted file mode 100644
index f4527a84..00000000
--- a/lpld/templates/atoms/heading/heading-block.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-context:
- value:
- text: 'Heading'
diff --git a/lpld/templates/atoms/heading/heading.html b/lpld/templates/atoms/heading/heading.html
index 6321afd5..d7d58cfe 100644
--- a/lpld/templates/atoms/heading/heading.html
+++ b/lpld/templates/atoms/heading/heading.html
@@ -1,19 +1,11 @@
{% load slippers %}
{% var level=level|default:"1" %}
-{% var size=size|default:"lg" %}
{% spaceless %}