diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/LICENSE b/packages/preview/cleanified-hpi-thesis/0.2.0/LICENSE
new file mode 100644
index 0000000000..28f1e098e7
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025-2026 Robert Richter and Felix Hoffmann
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/README.md b/packages/preview/cleanified-hpi-thesis/0.2.0/README.md
new file mode 100644
index 0000000000..afd7f6efdb
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/README.md
@@ -0,0 +1,71 @@
+# HPI Thesis Template
+
+This template is for HPI students writing their Bachelor's or Master's thesis.
+
+## Disclaimer
+
+- This template is not official.
+- Official university guidelines may differ from the ones used in this template.
+
+## Getting Started
+
+```bash
+typst init @preview/cleanified-hpi-thesis
+```
+
+## Configuration
+
+An example configuration is located in [`example/`](./example/main.typ).
+
+```typst
+#import "@preview/cleanified-hpi-thesis:0.2.0": *
+
+#show: project.with(
+ title: "My Very Long, Informative, Expressive, and Definitely Fancy Title",
+ translation: "Eine adäquate Übersetzung meines Titels",
+ name: "Max Mustermann",
+ date: "17. Juli, 2025",
+ study-program: "IT-Systems Engineering",
+ chair: "Data-Intensive Internet Computing",
+ professors: ("Prof. Dr. Rosseforp Renttalp", "Prof. Dr. Erika Mustermann"),
+ advisors: ("Dr. Karla Musterfrau",),
+ abstract: "Some abstract",
+ abstract-de: "Der deutsche Abstract...",
+ acknowledgements: "Thanks to ...",
+ // acronyms: [API -- Application Programming Interface],
+ // ai-declaration: [Describe any use of generative AI tools here.],
+ type: "Master",
+ bibliography: bibliography("references.bib"),
+ // lang: "de",
+ // typography: (font: "STIX Two Text", body-text-size: 12pt),
+ // layout: (for-print: true, toc-depth: 2),
+ // appearance: (accent-color: rgb("#B1063A")),
+ // labels: (declaration-city: "Berlin"),
+)
+
+... your content ...
+```
+
+`professors` and `advisors` are ordered tuples. Their entries appear in the
+given order, one name per line, on the title page. A tuple containing one person
+requires a trailing comma, for example `("Dr. Karla Musterfrau",)`.
+
+Set `acronyms` to optional content that should appear after the acknowledgements
+and before the table of contents. The template does not prescribe how that
+content is generated, so it can be supplied by a glossary package or written
+directly.
+
+Set `ai-declaration` to disclose the use of generative AI tools in the final,
+signed declaration of authorship. The disclosure is placed after the authorship
+statement and before the place, date, and signature. When the option is left
+empty, the regular declaration of authorship is rendered unchanged. The
+combined title is localized through `lang` and can be overridden with the
+`ai-declaration-title` label.
+
+Keep the declaration concise. If detailed documentation of tools, prompts, or
+affected passages is required, place it in an appendix and refer to it from the
+declaration.
+
+## Logo Usage
+
+Please note the logo usage guidelines of University of Potsdam ([UP Logo Usage Guidelines](https://www.uni-potsdam.de/fileadmin/projects/zim/files/MMP/PDF_Dateien_MMP/250509-Leitfaden_DigitalPrint-web.pdf)) and Hasso Plattner Institute ([HPI Logo Usage Guidelines](https://hpi.de/en/imprint/)). The logos are subject to copyright of the respective institutions.
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/example/main.typ b/packages/preview/cleanified-hpi-thesis/0.2.0/example/main.typ
new file mode 100644
index 0000000000..590d9924f7
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/example/main.typ
@@ -0,0 +1,55 @@
+// For local development, replace the import below with:
+// #import "../template/lib.typ": *
+#import "@preview/cleanified-hpi-thesis:0.2.0": *
+
+#let abstract = [
+ This is a very good abstract.
+]
+
+#let abstract-de = [
+ Die ist eine wirklich gute Zusammenfassung.
+]
+
+#let acknowledgements = [
+ Thanks to ...
+]
+
+#show: project.with(
+ title: "My Very Long, Informative, Expressive, and Definitely Fancy Title",
+ translation: "Eine adäquate Übersetzung meines Titels",
+ name: "Max Mustermann",
+ date: "17. Juli, 2025",
+ study-program: "IT-Systems Engineering",
+ chair: "Data-Intensive Internet Computing",
+ professors: ("Prof. Dr. Rosseforp Renttalp", "Prof. Dr. Erika Mustermann"),
+ advisors: ("Dr. Karla Musterfrau",),
+ abstract: abstract,
+ abstract-de: abstract-de,
+ acknowledgements: acknowledgements,
+ // acronyms: [API -- Application Programming Interface],
+ // ai-declaration: [Describe any use of generative AI tools here.],
+ type: "Master",
+ bibliography: bibliography("references.bib"),
+ // lang: "de", // Switch all labels to German defaults
+ // typography: (font: "STIX Two Text", body-text-size: 12pt),
+ // layout: (for-print: true, toc-depth: 2),
+ // appearance: (accent-color: rgb("#B1063A")),
+ // labels: (declaration-city: "Berlin"),
+)
+
+= Introduction
+#lorem(80)
+
+As shown by Doe and Smith @example2025, this approach is effective.
+
+== In this paper
+#lorem(20)
+
+=== Contributions
+#lorem(40)
+
+==== Really Small Stuff
+#lorem(20)
+
+= Related Work
+#lorem(500)
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/example/references.bib b/packages/preview/cleanified-hpi-thesis/0.2.0/example/references.bib
new file mode 100644
index 0000000000..f8752897a3
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/example/references.bib
@@ -0,0 +1,9 @@
+@article{example2025,
+ author = {Jane Doe and John Smith},
+ title = {An Example Article for Demonstration},
+ journal = {Journal of Examples},
+ year = {2025},
+ volume = {1},
+ number = {1},
+ pages = {1--10},
+}
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/template/hpi-logo.svg b/packages/preview/cleanified-hpi-thesis/0.2.0/template/hpi-logo.svg
new file mode 100644
index 0000000000..b0e0504426
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/template/hpi-logo.svg
@@ -0,0 +1,69 @@
+
+
+
+
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/template/hpi-title-page.typ b/packages/preview/cleanified-hpi-thesis/0.2.0/template/hpi-title-page.typ
new file mode 100644
index 0000000000..710160a9b4
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/template/hpi-title-page.typ
@@ -0,0 +1,102 @@
+#let value-type = type
+
+#let render-people(people, field) = {
+ assert(
+ value-type(people) == array,
+ message: field + " must be an ordered tuple, for example (\"Name\",)",
+ )
+ people.map(person => [#person]).join(linebreak())
+}
+
+#let hpi-title-page(
+ professors: (),
+ advisors: (),
+ chair: "",
+ name: "",
+ title: "",
+ translation: "",
+ study-program: "",
+ date: none,
+ type: "",
+ accent-color: rgb("#4f5358"),
+ university-logo: "up-logo.svg",
+ institute-logo: "hpi-logo.svg",
+ labels: (:),
+) = {
+ assert(
+ type in ("Bachelor", "Master", ""),
+ message: "type must be 'Bachelor' or 'Master'",
+ )
+
+ let rendered-professors = render-people(professors, "professors")
+ let rendered-advisors = render-people(advisors, "advisors")
+
+ let (thesis-kind, degree, abbreviation) = if type == "Master" {
+ (
+ labels.at("master-thesis-kind"),
+ labels.at("master-degree"),
+ labels.at("master-abbreviation"),
+ )
+ } else {
+ (
+ labels.at("bachelor-thesis-kind"),
+ labels.at("bachelor-degree"),
+ labels.at("bachelor-abbreviation"),
+ )
+ }
+
+ page(footer: [])[
+ // Title page
+ #grid(
+ columns: (1fr, 1fr),
+ rows: (80pt, 80pt),
+ grid.cell(image(university-logo, alt: "University logo")),
+ grid.cell(align(right, image(
+ institute-logo,
+ alt: "Institute logo",
+ ))),
+ )
+
+ #align(center, block[
+ #line(length: 100%, stroke: 0.75pt + accent-color)\
+ #text(2em, weight: "bold", title) \ \
+ #text(1.5em, translation) \ \
+ #line(length: 100%, stroke: 0.75pt + accent-color)
+ ])
+
+ #align(center, text(1.5em, weight: "bold", name))
+
+ #align(center, block[
+ #thesis-kind\
+ #labels.at("thesis-purpose")
+ ])
+
+ #align(center, text(1.5em, block[
+ #degree \
+ #text(style: "italic", "(" + abbreviation + ")")
+ ]))
+
+ #align(center, block[
+ #labels.at("study-program-label") \
+ #study-program
+ ])
+
+ #align(center, block[
+ #labels.at("submitted-on") #date #labels.at("submitted-on-suffix") \
+ #labels.at("chair-label") #chair #labels.at("chair-suffix") \
+ #labels.at("faculty") \
+ #labels.at("university")
+ ])
+
+ #v(1cm)
+ #align(center, grid(
+ columns: (1fr, 1.8fr),
+ rows: (auto, auto),
+ row-gutter: 6pt,
+ grid.cell(align(left + top, text(weight: "bold", labels.at("examiner")))),
+ grid.cell(align(left + top, rendered-professors)),
+ grid.cell(align(left + top, text(weight: "bold", labels.at("advisor")))),
+ grid.cell(align(left + top, rendered-advisors)),
+ ))
+ ]
+}
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/template/lib.typ b/packages/preview/cleanified-hpi-thesis/0.2.0/template/lib.typ
new file mode 100644
index 0000000000..75be4541cb
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/template/lib.typ
@@ -0,0 +1,399 @@
+#let std-bibliography = bibliography
+
+#import "hpi-title-page.typ": hpi-title-page
+
+// Default label sets for English and German.
+// English labels use German strings for the title page because HPI requires
+// a German title page regardless of thesis language. Only structural labels
+// (abstract, contents, declaration, etc.) are translated to English.
+#let default-labels-en = (
+ abstract: "Abstract",
+ abstract-de: "Zusammenfassung",
+ acknowledgements: "Acknowledgements",
+ acronyms: "List of Acronyms",
+ ai-declaration-title: "Declaration of Authorship and Use of Generative AI",
+ contents: "Contents",
+ bibliography: "Bibliography",
+ declaration-title: "Declaration of Authorship",
+ declaration-text: [
+ I hereby declare that this thesis is my own unaided work. All direct or
+ indirect sources used are acknowledged as references.
+ ],
+ declaration-city: "Potsdam",
+ thesis-purpose: "zur Erlangung des akademischen Grades",
+ study-program-label: "im Studiengang",
+ submitted-on: "eingereicht am",
+ submitted-on-suffix: "am",
+ chair-label: "Fachgebiet",
+ chair-suffix: "der",
+ faculty: "Digital-Engineering-Fakultät",
+ university: "der Universität Potsdam",
+ examiner: "Gutachter",
+ advisor: "Betreuer",
+ bachelor-thesis-kind: "Universitätsbachelorarbeit",
+ bachelor-degree: "Bachelor of Science",
+ bachelor-abbreviation: "B.Sc.",
+ master-thesis-kind: "Universitätsmasterarbeit",
+ master-degree: "Master of Science",
+ master-abbreviation: "M.Sc.",
+)
+
+#let default-labels-de = (
+ abstract: "Zusammenfassung (Englisch)",
+ abstract-de: "Zusammenfassung",
+ acknowledgements: "Danksagung",
+ acronyms: "Abkürzungsverzeichnis",
+ ai-declaration-title: [
+ Eigenständigkeitserklärung mit Angaben zur Nutzung von KI-Werkzeugen
+ ],
+ contents: "Inhaltsverzeichnis",
+ bibliography: "Literaturverzeichnis",
+ declaration-title: "Eigenständigkeitserklärung",
+ declaration-text: [
+ Ich erkläre hiermit, dass ich die vorliegende Arbeit selbstständig verfasst
+ und keine anderen als die angegebenen Quellen und Hilfsmittel verwendet
+ habe.
+ ],
+ declaration-city: "Potsdam",
+ thesis-purpose: "zur Erlangung des akademischen Grades",
+ study-program-label: "im Studiengang",
+ submitted-on: "eingereicht am",
+ submitted-on-suffix: "am",
+ chair-label: "Fachgebiet",
+ chair-suffix: "der",
+ faculty: "Digital-Engineering-Fakultät",
+ university: "der Universität Potsdam",
+ examiner: "Gutachter",
+ advisor: "Betreuer",
+ bachelor-thesis-kind: "Universitätsbachelorarbeit",
+ bachelor-degree: "Bachelor of Science",
+ bachelor-abbreviation: "B.Sc.",
+ master-thesis-kind: "Universitätsmasterarbeit",
+ master-degree: "Master of Science",
+ master-abbreviation: "M.Sc.",
+)
+
+// Default typography settings (font, sizes, spacing).
+#let default-typography = (
+ font: "Libertinus Serif",
+ body-text-size: 11pt,
+ line-spacing: 0.65em,
+ justify: true,
+ heading-sizes: (h1: 20pt, h2: 16pt, h3: 14pt, h4: 12pt, fallback: 11pt),
+)
+
+// Default layout settings (margins, print mode, ToC depth).
+#let default-layout = (
+ margin: (left: 35mm, right: 35mm, top: 30mm, bottom: 30mm),
+ for-print: false,
+ chapter-pagebreak: false,
+ toc-depth: 4,
+)
+
+// Default appearance settings (colors, logos).
+#let default-appearance = (
+ accent-color: rgb("#4f5358"),
+ university-logo: "up-logo.svg",
+ institute-logo: "hpi-logo.svg",
+)
+
+// The project function defines how your document looks.
+// It takes your content and some metadata and formats it.
+// Go ahead and customize it to your liking!
+#let project(
+ // The title of the thesis
+ title: "",
+ // The translated title of the thesis
+ translation: "",
+ // The name of the student writing the thesis
+ name: "",
+ // Date of handing in the thesis
+ date: none,
+ // "Bachelor" or "Master"
+ type: "",
+ // Study Program of the student
+ study-program: "",
+ // Chair where the thesis is written
+ chair: "",
+ // Ordered tuple of examining professors
+ professors: (),
+ // Ordered tuple of advisors
+ advisors: (),
+ // The abstract of the thesis
+ abstract: "",
+ // The German translation of the abstract
+ // If not given, the page for German translation of abstract will not appear
+ abstract-de: "",
+ // The student may want to add acknowledgements
+ // If not given, the page for acknowledgements will not appear
+ acknowledgements: "",
+ // Optional acronym-list content
+ // If not given, the page for the acronym list will not appear
+ acronyms: none,
+ // Optional declaration describing the use of generative AI tools
+ // If given, it is included in the final declaration of authorship
+ ai-declaration: "",
+ // Optional bibliography content (e.g., bibliography("references.bib")).
+ // If provided, a bibliography section will be added at the end.
+ bibliography: none,
+ // Document language (e.g., "en", "de"). Affects label defaults.
+ lang: "en",
+ // Typography settings (font, sizes, spacing). Merged with defaults.
+ typography: (:),
+ // Layout settings (margins, print mode, ToC depth). Merged with defaults.
+ layout: (:),
+ // Appearance settings (colors, logos). Merged with defaults.
+ appearance: (:),
+ // Override any translatable string. Merged on top of the language defaults.
+ labels: (:),
+ body,
+) = {
+ // Merge group defaults with user overrides.
+ let typo = default-typography + typography
+ let typo = (
+ typo
+ + (
+ heading-sizes: default-typography.heading-sizes
+ + typography.at("heading-sizes", default: (:)),
+ )
+ )
+ let lay = default-layout + layout
+ let app = default-appearance + appearance
+
+ // Merge label defaults with user overrides.
+ let base-labels = if lang == "de" { default-labels-de } else {
+ default-labels-en
+ }
+ let valid-keys = base-labels.keys()
+ for key in labels.keys() {
+ assert(key in valid-keys, message: "Unknown label key: " + key)
+ }
+ let l = base-labels + labels
+
+ // Set the document's basic properties.
+ set document(author: name, title: title)
+ set page(
+ margin: lay.margin,
+ numbering: "1",
+ number-align: end,
+ )
+ set text(font: typo.font, size: typo.body-text-size, lang: lang)
+ set par(leading: typo.line-spacing, justify: typo.justify)
+ show math.equation: set text(weight: 400)
+
+ hpi-title-page(
+ professors: professors,
+ name: name,
+ advisors: advisors,
+ title: title,
+ translation: translation,
+ study-program: study-program,
+ chair: chair,
+ type: type,
+ date: date,
+ accent-color: app.accent-color,
+ university-logo: app.university-logo,
+ institute-logo: app.institute-logo,
+ labels: l,
+ )
+
+ // Helper to render a heading with its numbering.
+ let styled-heading(
+ it,
+ size,
+ fill,
+ spacing-before,
+ spacing-after,
+ underline: false,
+ ) = {
+ let number = if it.numbering != none {
+ counter(heading).display(it.numbering)
+ h(7pt, weak: true)
+ }
+
+ v(spacing-before)
+ text(size: size, fill: fill, weight: "bold", block([#number #it.body]))
+ if underline { line(length: 100%, stroke: 2pt + fill) }
+ v(spacing-after)
+ }
+
+ // Configure chapter headings (level 1).
+ show heading.where(level: 1): it => {
+ if lay.chapter-pagebreak { pagebreak(weak: true) }
+ styled-heading(it, typo.heading-sizes.at("h1"), app.accent-color, 5%, 1.5em)
+ }
+
+ // Configure section headings (levels 2-4).
+ show heading.where(level: 2): it => styled-heading(
+ it,
+ typo.heading-sizes.at("h2"),
+ app.accent-color,
+ 2%,
+ 0.75em,
+ )
+ show heading.where(level: 3): it => styled-heading(
+ it,
+ typo.heading-sizes.at("h3"),
+ app.accent-color,
+ 2%,
+ 0pt,
+ )
+ show heading.where(level: 4): it => styled-heading(
+ it,
+ typo.heading-sizes.at("h4"),
+ app.accent-color,
+ 2%,
+ 0pt,
+ )
+
+ // Fallback for deeper heading levels.
+ show heading: set text(typo.heading-sizes.at("fallback"), weight: 400)
+
+ // Helper: insert a front matter section followed by a page break.
+ let front-section(title-text, content) = {
+ heading(level: 1, numbering: none, title-text)
+ v(0.5cm)
+ content
+ pagebreak()
+ if lay.for-print { pagebreak() }
+ }
+
+ // Front matter (unnumbered pages).
+ set page(numbering: none)
+ pagebreak()
+ if lay.for-print { pagebreak() }
+
+ // Roman-numbered front matter.
+ counter(page).update(1)
+ set page(numbering: "i")
+
+ front-section(l.at("abstract"), abstract)
+
+ if abstract-de != "" {
+ front-section(l.at("abstract-de"), abstract-de)
+ }
+
+ if acknowledgements != "" {
+ front-section(l.at("acknowledgements"), acknowledgements)
+ }
+
+ if acronyms != none {
+ front-section(l.at("acronyms"), acronyms)
+ }
+
+ // Table of contents.
+ outline(
+ title: [
+ #text(
+ size: typo.heading-sizes.at("h1"),
+ fill: app.accent-color,
+ l.at("contents"),
+ )
+ ],
+ depth: lay.toc-depth,
+ )
+ pagebreak()
+ if lay.for-print { pagebreak() }
+
+ // Main body.
+
+ // Creates a pagebreak to the given parity where empty pages
+ // can be detected via `is-page-empty`.
+ let detectable-pagebreak(to: "odd") = {
+ [#metadata(none) ]
+ pagebreak(to: to)
+ [#metadata(none) ]
+ }
+
+ // Workaround for https://github.com/typst/typst/issues/2722
+ let is-page-empty() = {
+ let page-num = here().page()
+ query()
+ .zip(query())
+ .any(((start, end)) => {
+ (
+ start.location().page() < page-num
+ and page-num < end.location().page()
+ )
+ })
+ }
+
+ // Mark the start of the main body for header page number calculation.
+ [#metadata(none) ]
+
+ // Configure page properties.
+ set page(
+ numbering: "1",
+ header: context {
+ if is-page-empty() {
+ return
+ }
+
+ // Calculate the body page number relative to the start of the main body.
+ let body-start-page = query().first().location().page()
+ let i = here().page() - body-start-page + 1
+
+ // Skip headers on pages that start a chapter heading (level 1 only).
+ if query(heading.where(level: 1)).any(it => (
+ it.location().page() == here().page()
+ )) {
+ return
+ }
+
+ // Find the heading of the section we are currently in.
+ let before = query(selector(heading).before(here()))
+ if before != () {
+ set text(0.95em)
+ let author = text(style: "italic", name)
+ grid(
+ columns: (1fr, 10fr, 1fr),
+ align: (left, center, right),
+ if calc.even(i) [#i],
+ if calc.even(i) { author } else { title },
+ if calc.odd(i) [#i],
+ )
+ }
+ align(center, line(length: 100%, stroke: 0.5pt + app.accent-color))
+ },
+ )
+ set heading(numbering: "1.1.1.1")
+
+ counter(page).update(1)
+ body
+
+ // Bibliography.
+ if bibliography != none {
+ pagebreak()
+ set std-bibliography(title: l.at("bibliography"))
+ bibliography
+ }
+
+ pagebreak()
+ if lay.for-print { pagebreak() }
+ let declaration-heading = if ai-declaration == "" {
+ l.at("declaration-title")
+ } else {
+ l.at("ai-declaration-title")
+ }
+ heading(level: 1, numbering: none, declaration-heading)
+
+ v(0.5cm)
+ block(l.at("declaration-text"))
+
+ if ai-declaration != "" {
+ v(1cm)
+ block(ai-declaration)
+ }
+
+ v(1.5cm)
+ [#l.at("declaration-city"), #date]
+ v(1cm)
+ grid(
+ columns: (1fr, 1fr),
+ [],
+ [
+ #line(length: 100%, stroke: 0.5pt)
+ #align(center, name)
+ ],
+ )
+}
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/template/up-logo.svg b/packages/preview/cleanified-hpi-thesis/0.2.0/template/up-logo.svg
new file mode 100644
index 0000000000..4ca5edc922
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/template/up-logo.svg
@@ -0,0 +1,164 @@
+
+
+
+
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/thumbnail.png b/packages/preview/cleanified-hpi-thesis/0.2.0/thumbnail.png
new file mode 100644
index 0000000000..e23c2c290c
Binary files /dev/null and b/packages/preview/cleanified-hpi-thesis/0.2.0/thumbnail.png differ
diff --git a/packages/preview/cleanified-hpi-thesis/0.2.0/typst.toml b/packages/preview/cleanified-hpi-thesis/0.2.0/typst.toml
new file mode 100644
index 0000000000..114b7c3da9
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.2.0/typst.toml
@@ -0,0 +1,37 @@
+[package]
+name = "cleanified-hpi-thesis"
+version = "0.2.0"
+entrypoint = "template/lib.typ"
+authors = [
+ "Robert Richter ",
+ "Felix Hoffmann ",
+]
+license = "MIT"
+disciplines = [
+ "computer-science",
+ "engineering",
+ "mathematics",
+ "medicine",
+ "business",
+]
+description = "A clean thesis template for Bachelor's and Master's theses at HPI, University of Potsdam."
+repository = "https://github.com/felixhoffmnn/hpi-thesis-template"
+keywords = [
+ "HPI",
+ "Hasso-Plattner-Institut",
+ "Hasso Plattner Institute",
+ "University of Potsdam",
+ "Bachelorthesis",
+ "Masterthesis",
+ "Bachelorarbeit",
+ "Masterarbeit",
+ "thesis",
+]
+categories = ["thesis"]
+compiler = "0.14.0"
+exclude = ["example/main.pdf"]
+
+[template]
+path = "example"
+entrypoint = "main.typ"
+thumbnail = "thumbnail.png"
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/LICENSE b/packages/preview/cleanified-hpi-thesis/0.3.0/LICENSE
new file mode 100644
index 0000000000..28f1e098e7
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025-2026 Robert Richter and Felix Hoffmann
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/README.md b/packages/preview/cleanified-hpi-thesis/0.3.0/README.md
new file mode 100644
index 0000000000..798fa4eb6c
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/README.md
@@ -0,0 +1,60 @@
+# HPI Thesis Template
+
+This template is for HPI students writing their Bachelor's or Master's thesis.
+
+**Note:** This is an unofficial template; current university guidelines take precedence.
+
+## Getting Started
+
+```bash
+typst init @preview/cleanified-hpi-thesis
+```
+
+## Configuration
+
+An example configuration is located in [`example/`](./example/main.typ).
+
+```typst
+#import "@preview/cleanified-hpi-thesis:0.3.0": *
+
+#show: project.with(
+ title: "My Thesis",
+ translation: "Meine Abschlussarbeit",
+ name: "Max Mustermann", date: "17. Juli 2026", type: "Master",
+ study-program: "IT-Systems Engineering", chair: "Data-Intensive Internet Computing",
+ professors: ("Prof. Erika Mustermann",), advisors: ("Dr. Karla Musterfrau",),
+ // lang: "de",
+ // typography: (font: "STIX Two Text", body-text-size: 12pt),
+ // layout: (for-print: true, toc-depth: 2),
+ // appearance: (accent-color: rgb("#B1063A")),
+ // labels: (declaration-city: "Berlin"),
+)
+
+#abstract[English abstract.]
+#abstract-de[Deutsche Zusammenfassung.]
+#acknowledgements[Thanks to ...]
+#acronyms[API -- Application Programming Interface]
+#ai-declaration[Describe your use of generative AI tools.]
+
+= Introduction
+Write your thesis here.
+
+#bibliography("references.bib")
+
+#appendix[
+ == Additional Results
+]
+```
+
+## Logo Usage
+
+Please note the logo usage guidelines of University of Potsdam ([UP Logo Usage Guidelines](https://www.uni-potsdam.de/fileadmin/projects/zim/files/MMP/PDF_Dateien_MMP/250509-Leitfaden_DigitalPrint-web.pdf)) and Hasso Plattner Institute ([HPI Logo Usage Guidelines](https://hpi.de/en/imprint/)). The logos are subject to copyright of the respective institutions.
+
+## Changelog
+
+| Version tag | Breaking | Core changes |
+| --- | --- | --- |
+| `0.3.0` | Yes | On-demand section markers, native bibliography, appendices, and layout refinements. |
+| `0.2.0` | Yes | Tuple-based professors and advisors, acronyms, and AI declarations. |
+| `0.1.0` | Yes | Package rename and grouped configuration API. |
+| `0.0.1` | No | Initial HPI thesis template. |
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/example/main.typ b/packages/preview/cleanified-hpi-thesis/0.3.0/example/main.typ
new file mode 100644
index 0000000000..89ad350eb2
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/example/main.typ
@@ -0,0 +1,64 @@
+// For local development, replace the import below with:
+// #import "../template/lib.typ": *
+#import "@preview/cleanified-hpi-thesis:0.3.0": *
+
+#show: project.with(
+ title: "My Very Long, Informative, Expressive, and Definitely Fancy Title",
+ translation: "Eine adäquate Übersetzung meines Titels",
+ name: "Max Mustermann",
+ date: "17. Juli, 2025",
+ study-program: "IT-Systems Engineering",
+ chair: "Data-Intensive Internet Computing",
+ professors: ("Prof. Dr. Rosseforp Renttalp", "Prof. Dr. Erika Mustermann"),
+ advisors: ("Dr. Karla Musterfrau",),
+ type: "Master",
+ // lang: "de", // Switch all labels to German defaults
+ // typography: (font: "STIX Two Text", body-text-size: 12pt),
+ // layout: (for-print: true, toc-depth: 2),
+ // appearance: (accent-color: rgb("#B1063A")),
+ // labels: (declaration-city: "Berlin"),
+)
+
+#abstract[
+ This is a very good abstract.
+]
+
+#abstract-de[
+ Dies ist eine wirklich gute Zusammenfassung.
+]
+
+#acknowledgements[
+ Thanks to ...
+]
+
+// #acronyms[
+// API -- Application Programming Interface
+// ]
+
+// #ai-declaration[
+// Describe any use of generative AI tools here.
+// ]
+
+= Introduction
+#lorem(80)
+
+As shown by Doe and Smith @example2025, this approach is effective.
+
+== In this paper
+#lorem(20)
+
+=== Contributions
+#lorem(40)
+
+==== Really Small Stuff
+#lorem(20)
+
+= Related Work
+#lorem(500)
+
+#bibliography("references.bib")
+
+#appendix[
+ == Additional Results
+ #lorem(80)
+]
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/example/references.bib b/packages/preview/cleanified-hpi-thesis/0.3.0/example/references.bib
new file mode 100644
index 0000000000..f8752897a3
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/example/references.bib
@@ -0,0 +1,9 @@
+@article{example2025,
+ author = {Jane Doe and John Smith},
+ title = {An Example Article for Demonstration},
+ journal = {Journal of Examples},
+ year = {2025},
+ volume = {1},
+ number = {1},
+ pages = {1--10},
+}
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/template/hpi-logo.svg b/packages/preview/cleanified-hpi-thesis/0.3.0/template/hpi-logo.svg
new file mode 100644
index 0000000000..b0e0504426
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/template/hpi-logo.svg
@@ -0,0 +1,69 @@
+
+
+
+
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/template/hpi-title-page.typ b/packages/preview/cleanified-hpi-thesis/0.3.0/template/hpi-title-page.typ
new file mode 100644
index 0000000000..77da299f31
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/template/hpi-title-page.typ
@@ -0,0 +1,113 @@
+#let value-type = type
+
+#let render-people(people, field) = {
+ assert(
+ value-type(people) == array,
+ message: field + " must be an ordered tuple, for example (\"Name\",)",
+ )
+ people.map(person => [#person]).join(linebreak())
+}
+
+#let hpi-title-page(
+ professors: (),
+ advisors: (),
+ chair: "",
+ name: "",
+ title: "",
+ translation: "",
+ study-program: "",
+ date: none,
+ type: "",
+ accent-color: rgb("#4f5358"),
+ university-logo: "up-logo.svg",
+ institute-logo: "hpi-logo.svg",
+ labels: (:),
+) = {
+ assert(
+ type in ("Bachelor", "Master", ""),
+ message: "type must be 'Bachelor' or 'Master'",
+ )
+
+ let rendered-professors = render-people(professors, "professors")
+ let rendered-advisors = render-people(advisors, "advisors")
+ let examiner-label = labels.at(
+ if professors.len() == 1 { "examiner" } else { "examiners" },
+ )
+ let advisor-label = labels.at(
+ if advisors.len() == 1 { "advisor" } else { "advisors" },
+ )
+
+ let (thesis-kind, degree, abbreviation) = if type == "Master" {
+ (
+ labels.at("master-thesis-kind"),
+ labels.at("master-degree"),
+ labels.at("master-abbreviation"),
+ )
+ } else {
+ (
+ labels.at("bachelor-thesis-kind"),
+ labels.at("bachelor-degree"),
+ labels.at("bachelor-abbreviation"),
+ )
+ }
+
+ page(footer: [])[
+ // Title page
+ #grid(
+ columns: (1fr, 1fr),
+ rows: (80pt, 80pt),
+ grid.cell(image(university-logo, alt: "University logo")),
+ grid.cell(align(right, image(
+ institute-logo,
+ alt: "Institute logo",
+ ))),
+ )
+
+ #align(center, block(
+ width: 100%,
+ inset: (x: 1em, y: 2em),
+ stroke: (
+ top: 0.75pt + accent-color,
+ bottom: 0.75pt + accent-color,
+ ),
+ )[
+ #text(2em, weight: "bold", title)
+ #if translation != "" [\ #v(0.5em) #text(1.5em, translation)]
+ ])
+
+ #align(center, text(1.5em, weight: "bold", name))
+
+ #align(center, block[
+ #thesis-kind\
+ #labels.at("thesis-purpose")
+ ])
+
+ #align(center, text(1.5em, block[
+ #degree \
+ #text(style: "italic", "(" + abbreviation + ")")
+ ]))
+
+ #align(center, block[
+ #labels.at("study-program-label") \
+ #study-program
+ ])
+
+ #align(center, block[
+ #labels.at("submitted-on") #date #labels.at("submitted-on-suffix") \
+ #labels.at("chair-label") #chair #labels.at("chair-suffix") \
+ #labels.at("faculty") \
+ #labels.at("university")
+ ])
+
+ #v(1cm)
+ #align(center, grid(
+ columns: (1fr, 1.8fr),
+ rows: (auto, auto),
+ row-gutter: 6pt,
+ grid.cell(align(left + top, text(weight: "bold", examiner-label))),
+ grid.cell(align(left + top, rendered-professors)),
+ grid.cell(align(left + top, text(weight: "bold", advisor-label))),
+ grid.cell(align(left + top, rendered-advisors)),
+ ))
+ ]
+}
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/template/lib.typ b/packages/preview/cleanified-hpi-thesis/0.3.0/template/lib.typ
new file mode 100644
index 0000000000..5d3de052fa
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/template/lib.typ
@@ -0,0 +1,390 @@
+#import "hpi-title-page.typ": hpi-title-page
+
+// On-demand document sections. Their content is collected and rendered by
+// `project`, so calls can stay next to the source they describe.
+#let abstract(body) = [#metadata(body) ]
+#let abstract-de(body) = [#metadata(body) ]
+#let acknowledgements(body) = [#metadata(body) ]
+#let acronyms(body) = [#metadata(body) ]
+#let ai-declaration(body) = [#metadata(body) ]
+#let appendix(body) = [#metadata(body) ]
+
+// Default label sets for English and German.
+// English labels use German strings for the title page because HPI requires
+// a German title page regardless of thesis language. Only structural labels
+// (abstract, contents, declaration, etc.) are translated to English.
+#let default-labels-en = (
+ abstract: "Abstract",
+ abstract-de: "Zusammenfassung",
+ acknowledgements: "Acknowledgements",
+ acronyms: "List of Acronyms",
+ chapter: "Chapter",
+ appendix: "Appendix",
+ ai-declaration-title: "Declaration of Authorship and Use of Generative AI",
+ contents: "Contents",
+ bibliography: "Bibliography",
+ declaration-title: "Declaration of Authorship",
+ declaration-text: [
+ I hereby declare that this thesis is my own unaided work. All direct or
+ indirect sources used are acknowledged as references.
+ ],
+ declaration-city: "Potsdam",
+ thesis-purpose: "zur Erlangung des akademischen Grades",
+ study-program-label: "im Studiengang",
+ submitted-on: "eingereicht am",
+ submitted-on-suffix: "am",
+ chair-label: "Fachgebiet",
+ chair-suffix: "der",
+ faculty: "Digital-Engineering-Fakultät",
+ university: "der Universität Potsdam",
+ examiner: "Gutachter",
+ examiners: "Gutachter",
+ advisor: "Betreuer",
+ advisors: "Betreuer",
+ bachelor-thesis-kind: "Universitätsbachelorarbeit",
+ bachelor-degree: "Bachelor of Science",
+ bachelor-abbreviation: "B.Sc.",
+ master-thesis-kind: "Universitätsmasterarbeit",
+ master-degree: "Master of Science",
+ master-abbreviation: "M.Sc.",
+)
+
+#let default-labels-de = default-labels-en + (
+ abstract: "Zusammenfassung (Englisch)",
+ abstract-de: "Zusammenfassung",
+ acknowledgements: "Danksagung",
+ acronyms: "Abkürzungsverzeichnis",
+ chapter: "Kapitel",
+ appendix: "Anhang",
+ ai-declaration-title: [
+ Eigenständigkeitserklärung mit Angaben zur Nutzung von KI-Werkzeugen
+ ],
+ contents: "Inhaltsverzeichnis",
+ bibliography: "Literaturverzeichnis",
+ declaration-title: "Eigenständigkeitserklärung",
+ declaration-text: [
+ Ich erkläre hiermit, dass ich die vorliegende Arbeit selbstständig verfasst
+ und keine anderen als die angegebenen Quellen und Hilfsmittel verwendet
+ habe.
+ ],
+)
+
+// Default typography settings (font, sizes, spacing).
+#let default-typography = (
+ font: "Libertinus Serif",
+ body-text-size: 11pt,
+ line-spacing: 0.65em,
+ justify: true,
+ table-text-size: 9pt,
+ caption-text-size: 9pt,
+ heading-sizes: (h1: 20pt, h2: 16pt, h3: 14pt, h4: 12pt, fallback: 11pt),
+)
+
+// Default layout settings (margins, print mode, ToC depth).
+#let default-layout = (
+ margin: (left: 35mm, right: 35mm, top: 30mm, bottom: 30mm),
+ for-print: false,
+ chapter-pagebreak: true,
+ toc-depth: 4,
+)
+
+// Default appearance settings (colors, logos).
+#let default-appearance = (
+ accent-color: rgb("#4f5358"),
+ university-logo: "up-logo.svg",
+ institute-logo: "hpi-logo.svg",
+)
+
+// The project function defines how your document looks.
+// It takes your content and some metadata and formats it.
+// Go ahead and customize it to your liking!
+#let project(
+ // The title of the thesis
+ title: "",
+ // The translated title of the thesis
+ translation: "",
+ // The name of the student writing the thesis
+ name: "",
+ // Date of handing in the thesis
+ date: none,
+ // "Bachelor" or "Master"
+ type: "",
+ // Study Program of the student
+ study-program: "",
+ // Chair where the thesis is written
+ chair: "",
+ // Ordered tuple of examining professors
+ professors: (),
+ // Ordered tuple of advisors
+ advisors: (),
+ // Document language (e.g., "en", "de"). Affects label defaults.
+ lang: "en",
+ // Typography settings (font, sizes, spacing). Merged with defaults.
+ typography: (:),
+ // Layout settings (margins, print mode, chapter breaks, ToC depth).
+ layout: (:),
+ // Appearance settings (colors, logos). Merged with defaults.
+ appearance: (:),
+ // Override any translatable string. Merged on top of the language defaults.
+ labels: (:),
+ body,
+) = {
+ // Merge group defaults with user overrides.
+ let typo = default-typography + typography
+ let typo = (
+ typo
+ + (
+ heading-sizes: default-typography.heading-sizes
+ + typography.at("heading-sizes", default: (:)),
+ )
+ )
+ let lay = default-layout + layout
+ let app = default-appearance + appearance
+
+ // Merge label defaults with user overrides.
+ let base-labels = if lang == "de" { default-labels-de } else {
+ default-labels-en
+ }
+ let valid-keys = base-labels.keys()
+ for key in labels.keys() {
+ assert(key in valid-keys, message: "Unknown label key: " + key)
+ }
+ let l = base-labels + labels
+
+ // Set the document's basic properties.
+ set document(author: name, title: title)
+ set page(margin: lay.margin)
+ set text(font: typo.font, size: typo.body-text-size, lang: lang)
+ set par(leading: typo.line-spacing, justify: typo.justify)
+ show table: set text(size: typo.table-text-size)
+ show figure.caption: set text(size: typo.caption-text-size)
+ show figure.where(kind: table): set figure.caption(position: top)
+ show math.equation: set text(weight: 400)
+
+ // Workaround for https://github.com/typst/typst/issues/2722
+ let is-page-empty() = {
+ let page-num = here().page()
+ query()
+ .zip(query())
+ .any(((start, end)) => (
+ start.location().page() < page-num and page-num < end.location().page()
+ ))
+ }
+
+ // Mark inserted print pages so their headers and footers can be suppressed.
+ let section-pagebreak(weak: false) = if lay.for-print {
+ [#metadata(none) ]
+ pagebreak(to: "odd", weak: weak)
+ [#metadata(none) ]
+ } else {
+ pagebreak(weak: weak)
+ }
+
+ let page-footer = context {
+ if not is-page-empty() {
+ align(
+ if lay.for-print and calc.even(here().page()) { start } else { end },
+ counter(page).display(),
+ )
+ }
+ }
+
+ hpi-title-page(
+ professors: professors,
+ name: name,
+ advisors: advisors,
+ title: title,
+ translation: translation,
+ study-program: study-program,
+ chair: chair,
+ type: type,
+ date: date,
+ accent-color: app.accent-color,
+ university-logo: app.university-logo,
+ institute-logo: app.institute-logo,
+ labels: l,
+ )
+
+ // Helper to render a heading with its numbering.
+ let styled-heading(it, size, spacing-before, spacing-after) = {
+ let number = if it.numbering != none {
+ counter(heading).display(it.numbering)
+ h(7pt, weak: true)
+ }
+
+ v(spacing-before)
+ text(
+ size: size,
+ fill: app.accent-color,
+ weight: "bold",
+ block([#number #it.body]),
+ )
+ v(spacing-after)
+ }
+
+ // Configure chapter headings (level 1).
+ show heading.where(level: 1): set heading(supplement: l.at("chapter"))
+ show heading.where(level: 1): it => {
+ if lay.chapter-pagebreak { section-pagebreak(weak: true) }
+ styled-heading(it, typo.heading-sizes.at("h1"), 5%, 1.5em)
+ }
+
+ // Configure section headings (levels 2-4).
+ show heading.where(level: 2): it => styled-heading(
+ it,
+ typo.heading-sizes.at("h2"),
+ 2%,
+ 0.75em,
+ )
+ show heading.where(level: 3): it => styled-heading(
+ it,
+ typo.heading-sizes.at("h3"),
+ 2%,
+ 0pt,
+ )
+ show heading.where(level: 4): it => styled-heading(
+ it,
+ typo.heading-sizes.at("h4"),
+ 2%,
+ 0pt,
+ )
+
+ // Fallback for deeper heading levels.
+ show heading: set text(typo.heading-sizes.at("fallback"), weight: 400)
+
+ // Helper: insert a front matter section followed by a page break.
+ let front-section(title-text, content) = {
+ heading(level: 1, numbering: none, title-text)
+ v(0.5cm)
+ content
+ section-pagebreak()
+ }
+
+ let marker-content(label) = query(label).map(it => it.value)
+
+ // Front matter (unnumbered pages).
+ set page(numbering: none)
+ section-pagebreak()
+
+ // Roman-numbered front matter.
+ counter(page).update(1)
+ set page(numbering: "i", footer: page-footer)
+
+ context {
+ for (label, title) in (
+ (, l.at("abstract")),
+ (, l.at("abstract-de")),
+ (, l.at("acknowledgements")),
+ (, l.at("acronyms")),
+ ) {
+ let content = marker-content(label)
+ if content != () { front-section(title, content.join(parbreak())) }
+ }
+
+ // Table of contents.
+ outline(
+ title: [
+ #text(
+ size: typo.heading-sizes.at("h1"),
+ fill: app.accent-color,
+ l.at("contents"),
+ )
+ ],
+ depth: lay.toc-depth,
+ )
+ section-pagebreak()
+ }
+
+ // Main body.
+
+ // Configure page properties.
+ set page(
+ numbering: "1",
+ footer: page-footer,
+ header: context {
+ if is-page-empty() {
+ return
+ }
+
+ // Skip headers on pages that start a chapter heading.
+ if query(heading.where(level: 1)).any(it => (
+ it.location().page() == here().page()
+ )) {
+ return
+ }
+
+ // Find the heading of the section we are currently in.
+ let before = query(selector(heading).before(here()))
+ if before != () {
+ set text(0.95em)
+ align(
+ center,
+ if calc.even(here().page()) {
+ text(style: "italic", name)
+ } else {
+ title
+ },
+ )
+ }
+ align(center, line(length: 100%, stroke: 0.5pt + app.accent-color))
+ },
+ )
+ set heading(numbering: "1.1.1.1")
+ // Native bibliographies keep their source position while sharing the
+ // template's localized title and page-break behavior.
+ set bibliography(title: l.at("bibliography"))
+ show bibliography: it => {
+ section-pagebreak(weak: true)
+ it
+ }
+
+ counter(page).update(1)
+ body
+
+ context {
+ let appendices = marker-content()
+ if appendices != () {
+ section-pagebreak()
+ heading(level: 1, numbering: none, l.at("appendix"))
+ counter(heading).update(0)
+ set heading(numbering: (..numbers) => numbering(
+ "A.1.1",
+ ..numbers.pos().slice(1),
+ ))
+ show heading.where(level: 2): set heading(supplement: l.at("appendix"))
+ appendices.join()
+ }
+
+ section-pagebreak()
+ let disclosures = marker-content()
+ heading(
+ level: 1,
+ numbering: none,
+ if disclosures == () {
+ l.at("declaration-title")
+ } else {
+ l.at("ai-declaration-title")
+ },
+ )
+
+ v(0.5cm)
+ block(l.at("declaration-text"))
+
+ for disclosure in disclosures {
+ v(1cm)
+ block(disclosure)
+ }
+
+ v(1.5cm)
+ [#l.at("declaration-city"), #date]
+ v(1cm)
+ grid(
+ columns: (1fr, 1fr),
+ [],
+ [
+ #line(length: 100%, stroke: 0.5pt)
+ #align(center, name)
+ ],
+ )
+ }
+}
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/template/up-logo.svg b/packages/preview/cleanified-hpi-thesis/0.3.0/template/up-logo.svg
new file mode 100644
index 0000000000..4ca5edc922
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/template/up-logo.svg
@@ -0,0 +1,164 @@
+
+
+
+
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/thumbnail.png b/packages/preview/cleanified-hpi-thesis/0.3.0/thumbnail.png
new file mode 100644
index 0000000000..c0774db83f
Binary files /dev/null and b/packages/preview/cleanified-hpi-thesis/0.3.0/thumbnail.png differ
diff --git a/packages/preview/cleanified-hpi-thesis/0.3.0/typst.toml b/packages/preview/cleanified-hpi-thesis/0.3.0/typst.toml
new file mode 100644
index 0000000000..c04db88261
--- /dev/null
+++ b/packages/preview/cleanified-hpi-thesis/0.3.0/typst.toml
@@ -0,0 +1,37 @@
+[package]
+name = "cleanified-hpi-thesis"
+version = "0.3.0"
+entrypoint = "template/lib.typ"
+authors = [
+ "Robert Richter ",
+ "Felix Hoffmann ",
+]
+license = "MIT"
+disciplines = [
+ "computer-science",
+ "engineering",
+ "mathematics",
+ "medicine",
+ "business",
+]
+description = "A clean thesis template for Bachelor's and Master's theses at HPI, University of Potsdam."
+repository = "https://github.com/felixhoffmnn/hpi-thesis-template"
+keywords = [
+ "HPI",
+ "Hasso-Plattner-Institut",
+ "Hasso Plattner Institute",
+ "University of Potsdam",
+ "Bachelorthesis",
+ "Masterthesis",
+ "Bachelorarbeit",
+ "Masterarbeit",
+ "thesis",
+]
+categories = ["thesis"]
+compiler = "0.14.0"
+exclude = ["example/main.pdf"]
+
+[template]
+path = "example"
+entrypoint = "main.typ"
+thumbnail = "thumbnail.png"