diff --git a/packages/preview/bean-upm/0.1.0/LICENSE b/packages/preview/bean-upm/0.1.0/LICENSE
new file mode 100644
index 0000000000..809a820612
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Tikitikitikidesuka
+
+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.
\ No newline at end of file
diff --git a/packages/preview/bean-upm/0.1.0/README.md b/packages/preview/bean-upm/0.1.0/README.md
new file mode 100644
index 0000000000..9a85b3f6bf
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/README.md
@@ -0,0 +1,60 @@
+# UPM Report Template for Typst
+
+Unofficial template for Universidad Politécnica de Madrid thesis and reports.
+
+This is a Typst version of the template originally developed by Blazaid at [https://github.com/blazaid/UPM-Report-Template.git](https://github.com/blazaid/UPM-Report-Template.git). My LaTeX version of it is also available at [https://github.com/Tikitikitikidesuka/typst-upm-report.git](https://github.com/Tikitikitikidesuka/typst-upm-report.git).
+
+## Parameters
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `title` | Title of your work | "Title of the Work" |
+| `author` | Author's name | "Author's name" |
+| `supervisor` | Supervisor's name | "Supervisor's Name" |
+| `date` | Document date | Today's date |
+| `acknowledgements` | Content for acknowledgements page (optional) | none |
+| `abstract-en` | Abstract text (optional) | none |
+| `keywords-en` | Keywords for abstract (optional) | none |
+| `license-name` | License name | "Creative Commons Attribution..." |
+| `license-logo` | Image content for license logo (optional) | CC BY-NC-SA logo image |
+| `license-link` | URL to license | CC BY-NC-SA 4.0 URL |
+| `university` | University name | "Universidad Politécnica de Madrid" |
+| `school-name` | Full school name | "E.T.S. de Ingeniería de Sistemas Informáticos" |
+| `school-address` | School address | Campus Sur UPM address |
+| `school-abbr` | School abbreviation | "ETSISI" |
+| `report-type` | Type of document | "Bachelor's thesis" |
+| `degree-name` | Degree program name | "Grado en Ingeniería de Tecnologías..." |
+| `school-color` | Primary color for headers and accents | Blue: `rgb(32, 130, 192)` |
+| `school-logo` | Image content for school logo | ETSISI logo image |
+| `school-watermark` | Image content for school watermark (optional) | UPM watermark image |
+| `bibliography-file` | Path to .bib file | "references.bib" |
+| `bibliography-style` | Citation style (ieee, apa, mla, etc.) | "ieee" |
+
+## Using the Template
+
+To start a new document with this template:
+
+```
+typst init @preview/bean-upm my-thesis
+cd my-thesis
+```
+
+Then edit `main.typ` and compile with:
+
+```
+typst compile main.typ
+```
+
+You can also use the [Typst web app](https://typst.app) and search for "bean-upm" in the template gallery.
+
+## Contributing to the Template
+
+If you're developing or modifying this template locally, compile from the repository root with:
+
+```
+typst compile --root . template/main.typ
+```
+
+## License
+
+This template is distributed under an MIT License.
diff --git a/packages/preview/bean-upm/0.1.0/src/assets/cc-by-nc-sa.svg b/packages/preview/bean-upm/0.1.0/src/assets/cc-by-nc-sa.svg
new file mode 100644
index 0000000000..514c251b7a
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/src/assets/cc-by-nc-sa.svg
@@ -0,0 +1,202 @@
+
+
+
diff --git a/packages/preview/bean-upm/0.1.0/src/assets/etsisi-logo.svg b/packages/preview/bean-upm/0.1.0/src/assets/etsisi-logo.svg
new file mode 100644
index 0000000000..7bf75c524f
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/src/assets/etsisi-logo.svg
@@ -0,0 +1,17 @@
+
+
diff --git a/packages/preview/bean-upm/0.1.0/src/assets/upm-watermark.png b/packages/preview/bean-upm/0.1.0/src/assets/upm-watermark.png
new file mode 100644
index 0000000000..fd1432036b
Binary files /dev/null and b/packages/preview/bean-upm/0.1.0/src/assets/upm-watermark.png differ
diff --git a/packages/preview/bean-upm/0.1.0/src/lib.typ b/packages/preview/bean-upm/0.1.0/src/lib.typ
new file mode 100644
index 0000000000..542cf6ab44
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/src/lib.typ
@@ -0,0 +1,484 @@
+#let upm-report(
+  // Cover page info
+  title: "Title of the Work",
+  author: "Author's name",
+  supervisor: "Supervisor's Name",
+  date: datetime.today(),
+  // Acknowledgements and Abstract
+  acknowledgements: none,
+  abstract-en: none,
+  keywords-en: none,
+  // License info
+  license-name: "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
+  license-logo: image("assets/cc-by-nc-sa.svg", width: 80pt),
+  license-link: "https://creativecommons.org/licenses/by-nc-sa/4.0/",
+  // School configuration
+  university: "Universidad Politécnica de Madrid",
+  school-name: "E.T.S. de Ingeniería de Sistemas Informáticos",
+  school-address: "Campus Sur UPM, Carretera de Valencia (A-3), km. 7\n28031, Madrid, España",
+  school-abbr: "ETSISI",
+  report-type: "Bachelor's thesis",
+  degree-name: "Grado en Ingeniería de Tecnologías de la Sociedad de la Información",
+  school-color: rgb(32, 130, 192),
+  school-logo: image("assets/etsisi-logo.svg", width: 50%),
+  school-watermark: image("assets/upm-watermark.png", width: 90%),
+  // Bibliography configuration
+  bibliography-file: none,
+  bibliography-style: "ieee",
+  body,
+) = {
+  // Cover page
+  page(
+    margin: 0cm,
+    numbering: none,
+  )[
+    // Left colored bar
+    #place(
+      left + top,
+      rect(
+        width: 2cm,
+        height: 100%,
+        fill: school-color,
+      ),
+    )
+
+    // School watermark
+    #if school-watermark != none {
+      place(
+        right + bottom,
+        school-watermark,
+      )
+    }
+
+    // Content
+    #pad(
+      left: 3cm,
+      right: 2cm,
+      top: 3cm,
+      bottom: 3cm,
+      {
+        set text(size: 12pt)
+
+        // Header info
+        upper(university)
+        linebreak()
+        text(weight: "bold")[#upper(school-name)]
+        linebreak()
+        upper(report-type)
+        linebreak()
+        text(weight: "bold")[#upper(degree-name)]
+
+        v(1fr)
+
+        // Title
+        set text(size: 34pt, weight: "bold")
+        set par(leading: 0.5em, justify: false)
+        title
+
+        v(1fr)
+
+        // Author and supervisor
+        set text(size: 14pt, weight: "regular")
+        text(weight: "bold")[Written by: ]
+        author
+        linebreak()
+        text(weight: "bold")[Supervised by: ]
+        supervisor
+        linebreak()
+        [Madrid, #date.display("[day]/[month]/[year]")]
+      },
+    )
+  ]
+
+  // Metadata and License
+  page(
+    header: none,
+    numbering: none,
+  )[
+    #v(1fr)
+
+    #set text(size: 12pt)
+    #set par(justify: false, leading: 0.65em)
+
+    // Document metadata
+    #emph(title)
+
+    // Tighter paragraph spacing just for author/supervisor/date
+    #[
+      #set par(spacing: 0.5em)
+
+      *Written by:* #author
+
+      *Supervised by:* #supervisor
+
+      #report-type, #date.display("[day]/[month]/[year]")
+    ]
+
+    *#school-name*
+
+    #school-address
+
+    #v(1.5em)
+    #line(length: 100%, stroke: 0.5pt)
+    #v(1em)
+
+    // License text and logo in grid layout
+    #grid(
+      columns: (1fr, auto),
+      column-gutter: 4em,
+      align: (left, right),
+      [
+        #set par(justify: true)
+        This work is licensed under #if license-link != none { link(license-link)[#license-name] } else {
+          license-name
+        }.
+      ],
+      if license-logo != none {
+        if license-link != none {
+          link(license-link)[#license-logo]
+        } else {
+          license-logo
+        }
+      },
+    )
+
+    #v(5em)
+  ]
+
+  // Acknowledgements page (optional)
+  if acknowledgements != none {
+    page(
+      header: none,
+      numbering: none,
+    )[
+      #set text(size: 12pt)
+
+      #block(
+        above: 0pt,
+        below: 25pt,
+        {
+          set text(size: 30pt, weight: "regular")
+          align(right)[Acknowledgements]
+          v(-0.9em)
+          line(length: 100%, stroke: 0.5pt)
+          v(0.5em)
+        },
+      )
+
+      #set par(justify: true, leading: 0.65em)
+      #acknowledgements
+    ]
+  }
+
+  // Abstract page (optional)
+  if abstract-en != none {
+    page(
+      header: none,
+      numbering: none,
+    )[
+      #set text(size: 12pt)
+
+      #block(
+        above: 0pt,
+        below: 25pt,
+        {
+          set text(size: 30pt, weight: "regular")
+          align(right)[Abstract]
+          v(-0.9em)
+          line(length: 100%, stroke: 0.5pt)
+          v(0.5em)
+        },
+      )
+
+      #set par(justify: true, leading: 0.65em)
+
+      #abstract-en
+
+      #if keywords-en != none [
+        #v(1em)
+        *Keywords:* #keywords-en
+      ]
+    ]
+  }
+
+  // Table of Contents
+  page(
+    header: none,
+    numbering: none,
+  )[
+    // Style the outline entries
+    #show outline.entry.where(level: 1): it => {
+      v(18pt, weak: true)
+      text(fill: school-color)[#strong(it)]
+    }
+
+    // Style level 2 entries in blue
+    #show outline.entry.where(level: 2): it => {
+      v(12pt, weak: true)
+      text(fill: school-color)[#it]
+    }
+
+    #set text(size: 12pt)
+
+    // Custom title styled like chapter headings
+    #block(
+      above: 0pt,
+      below: 25pt,
+      {
+        set text(size: 30pt, weight: "regular")
+        align(right)[Table of Contents]
+        v(-0.9em)
+        line(length: 100%, stroke: 0.5pt)
+        v(0.5em)
+      },
+    )
+
+    #set par(leading: 1.8em)
+
+    #outline(
+      title: none,
+      depth: 2,
+      indent: auto,
+    )
+  ]
+
+  // List of Figures (optional - only shows if document has figures)
+  context {
+    let figures = query(figure.where(kind: image))
+    if figures.len() > 0 {
+      page(
+        header: none,
+        numbering: none,
+      )[
+        // Style outline entries in blue with spacing
+        #show outline.entry: it => {
+          v(12pt, weak: true)
+          text(fill: school-color)[#it]
+        }
+
+        #set text(size: 12pt)
+
+        #block(
+          above: 0pt,
+          below: 25pt,
+          {
+            set text(size: 30pt, weight: "regular")
+            align(right)[List of Figures]
+            v(-0.9em)
+            line(length: 100%, stroke: 0.5pt)
+            v(0.5em)
+          },
+        )
+
+        #set par(leading: 1.8em)
+
+        #outline(
+          title: none,
+          target: figure.where(kind: image),
+        )
+      ]
+    }
+  }
+
+  // List of Tables (optional - only shows if document has tables)
+  context {
+    let tables = query(figure.where(kind: table))
+    if tables.len() > 0 {
+      page(
+        header: none,
+        numbering: none,
+      )[
+        // Style outline entries in blue with spacing
+        #show outline.entry: it => {
+          v(12pt, weak: true)
+          text(fill: school-color)[#it]
+        }
+
+        #set text(size: 12pt)
+
+        #block(
+          above: 0pt,
+          below: 25pt,
+          {
+            set text(size: 30pt, weight: "regular")
+            align(right)[List of Tables]
+            v(-0.9em)
+            line(length: 100%, stroke: 0.5pt)
+            v(0.5em)
+          },
+        )
+
+        #set par(leading: 1.8em)
+
+        #outline(
+          title: none,
+          target: figure.where(kind: table),
+        )
+      ]
+    }
+  }
+
+  // Page setup for content
+  set page(
+    paper: "a4",
+    margin: (top: 3.5cm, bottom: 3cm, left: 2.5cm, right: 2.5cm),
+    header: context {
+      let page-num = counter(page).get().first()
+
+      // Don't show header on first page
+      if page-num <= 1 {
+        return
+      }
+
+      // Check if current page has a chapter heading
+      let current-page = here().page()
+      let headings-on-page = query(heading.where(level: 1)).filter(h => h.location().page() == current-page)
+
+      // Don't show header on pages with chapter headings
+      if headings-on-page.len() > 0 {
+        return
+      }
+
+      // Show header on all other pages
+      set text(fill: school-color, size: 10pt)
+
+      let chapter-title = {
+        let elems = query(heading.where(level: 1))
+        if elems.len() > 0 {
+          let relevant = elems.filter(h => h.location().page() <= current-page)
+          if relevant.len() > 0 {
+            upper(relevant.last().body)
+          }
+        }
+      }
+
+      grid(
+        columns: (1fr, auto),
+        align: (left, right),
+        chapter-title, counter(page).display(),
+      )
+      line(length: 100%, stroke: 0.5pt + school-color)
+    },
+  )
+
+  // Reset page counter for main content
+  counter(page).update(1)
+
+  // Text setup
+  set text(size: 12pt)
+
+  set par(
+    leading: 0.65em,
+    spacing: 1em,
+    justify: true,
+    first-line-indent: 0pt,
+  )
+
+  // Chapter headings (level 1)
+  show heading.where(level: 1): it => {
+    pagebreak(weak: true)
+    set text(size: 30pt, weight: "regular")
+    block(
+      above: 0pt,
+      below: 25pt,
+      spacing: 0pt,
+      {
+        set par(spacing: 0pt)
+        if it.numbering != none {
+          grid(
+            columns: (auto, 1fr),
+            column-gutter: 0.6em,
+            align: (left, right),
+            // Left side: number and dot in blue
+            text(fill: school-color)[#counter(heading).display().],
+            // Right side: heading text in black
+            it.body,
+          )
+        } else {
+          // If no numbering, just right-align the text
+          align(right, it.body)
+        }
+        v(-0.9em)
+        line(length: 100%, stroke: 0.5pt)
+        v(0.5em)
+      },
+    )
+  }
+
+  // Section headings (level 2)
+  show heading.where(level: 2): it => {
+    set text(size: 20pt, weight: "medium")
+    block(
+      above: 1.5em,
+      below: 1em,
+      {
+        if it.numbering != none {
+          counter(heading).display()
+          [. ]
+        }
+        h(0.6em)
+        it.body
+      },
+    )
+  }
+
+  // Subsection headings (level 3)
+  show heading.where(level: 3): it => {
+    set text(size: 16pt, weight: "medium")
+    block(
+      above: 1.2em,
+      below: 0.8em,
+      {
+        if it.numbering != none {
+          counter(heading).display()
+          [. ]
+        }
+        h(0.6em)
+        it.body
+      },
+    )
+  }
+
+  set heading(numbering: "1.1")
+
+  body
+
+  // Bibliography section
+  if bibliography-file != none {
+    pagebreak()
+
+    // Style the bibliography heading
+    show bibliography: set heading(numbering: none)
+
+    bibliography(
+      bibliography-file,
+      title: [Bibliography],
+      style: bibliography-style,
+    )
+  }
+
+  // Back cover page
+  page(
+    margin: 0cm,
+    numbering: none,
+    header: none,
+    fill: black,
+  )[
+    // School-color rectangle covering top half
+    #place(
+      top + left,
+      rect(
+        width: 100%,
+        height: 50%,
+        fill: school-color,
+      ),
+    )
+
+    // School logo centered in bottom half
+    #place(
+      center + horizon,
+      dy: 25%,
+      school-logo,
+    )
+  ]
+}
diff --git a/packages/preview/bean-upm/0.1.0/template/assets/placeholder.png b/packages/preview/bean-upm/0.1.0/template/assets/placeholder.png
new file mode 100644
index 0000000000..05b98ee96e
Binary files /dev/null and b/packages/preview/bean-upm/0.1.0/template/assets/placeholder.png differ
diff --git a/packages/preview/bean-upm/0.1.0/template/main.typ b/packages/preview/bean-upm/0.1.0/template/main.typ
new file mode 100644
index 0000000000..5cfa2daf43
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/template/main.typ
@@ -0,0 +1,133 @@
+#import "@preview/bean-upm:0.1.0": upm-report
+
+#show: upm-report.with(
+  title: "This is an Example Thesis Title That You Should Replace",
+  author: "Jane Example Student",
+  supervisor: "Prof. Example McSupervisor",
+  date: datetime(year: 2025, month: 6, day: 15),
+
+  university: "Universidad Politécnica de Madrid",
+  school-name: "E.T.S. de Ingeniería de Sistemas Informáticos",
+  school-address: "Campus Sur UPM, Carretera de Valencia (A-3), km. 7\n28031, Madrid, España",
+  school-abbr: "ETSISI",
+  report-type: "Bachelor's thesis",
+  degree-name: "Grado en Ingeniería del Software",
+
+  acknowledgements: "Thanks to my family, friends, and colleagues for their support.",
+  abstract-en: "This thesis explores the fascinating world of example topics. It provides insights and analysis on various aspects of the subject matter, aiming to contribute to the existing body of knowledge.",
+  keywords-en: "example, thesis, typst, template",
+
+  bibliography-file: "../template/references.bib",
+  bibliography-style: "ieee",
+)
+
+= Introduction
+
+Hello! This is where your introduction goes. Replace this text with your actual introduction.
+
+You can cite things like this @fakebook2024, and it will appear in your bibliography at the end.
+
+== A Subsection
+
+You can have subsections too. Put your real content here instead of this placeholder text.
+
+Here go some images and tables to show in the lists:
+
+#figure(
+  image("assets/placeholder.png", width: 80%),
+  caption: [This is my figure caption],
+)
+
+#figure(
+  image("assets/placeholder.png", width: 80%),
+  caption: [This is my figure caption 2],
+)
+
+#figure(
+  image("assets/placeholder.png", width: 80%),
+  caption: [This is my figure caption 3],
+)
+
+#figure(
+  image("assets/placeholder.png", width: 80%),
+  caption: [This is my figure caption 4],
+)
+
+#figure(
+  table(
+    columns: 3,
+    [Header 1], [Header 2], [Header 3],
+    [Data 1], [Data 2], [Data 3],
+  ),
+  caption: [This is my table caption],
+)
+
+#figure(
+  table(
+    columns: 3,
+    [Header 1], [Header 2], [Header 3],
+    [Data 1], [Data 2], [Data 3],
+  ),
+  caption: [This is my table caption 2],
+)
+#figure(
+  table(
+    columns: 3,
+    [Header 1], [Header 2], [Header 3],
+    [Data 1], [Data 2], [Data 3],
+  ),
+  caption: [This is my table caption 3],
+)
+#figure(
+  table(
+    columns: 3,
+    [Header 1], [Header 2], [Header 3],
+    [Data 1], [Data 2], [Data 3],
+  ),
+  caption: [This is my table caption 4],
+)
+
+
+== Lists Work Too
+
+Here's how to make a list:
+
+- First item goes here
+- Second item goes here
+- Third item is also here
+
+And numbered lists:
+
++ Step one of something
++ Step two of something
++ Step three of something
+
+= Literature Review
+
+This is where you'd discuss what other people have written about your topic @anotherfakebook2023.
+
+You can have *bold text* and _italic text_ and even `code snippets` if you need them.
+
+= Methodology
+
+Explain how you did your work here. This section should describe your approach in detail.
+
+== Your Subsection Title
+
+Replace this with your actual methodology content.
+
+= Results
+
+Present your findings in this chapter. You could include tables, figures, and analysis here.
+
+= Discussion
+
+Discuss what your results mean and compare them with other work @yetanotherfake2022.
+
+= Conclusions
+
+Summarize your work and its contributions here.
+
+== Future Work
+
+Describe what could be done next to extend this work.
diff --git a/packages/preview/bean-upm/0.1.0/template/references.bib b/packages/preview/bean-upm/0.1.0/template/references.bib
new file mode 100644
index 0000000000..72ed3fcd6d
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/template/references.bib
@@ -0,0 +1,31 @@
+@book{fakebook2024,
+  title = {The Completely Made Up Guide to Example Citations},
+  author = {Smith, John Example and Doe, Jane Placeholder},
+  year = {2024},
+  publisher = {Fake Academic Press},
+}
+
+@article{anotherfakebook2023,
+  title = {A Study on Nothing in Particular},
+  author = {Example, Alice and Test, Bob},
+  journal = {Journal of Example Research},
+  year = {2023},
+  volume = {42},
+  number = {7},
+  pages = {123--456},
+}
+
+@inproceedings{yetanotherfake2022,
+  title = {Placeholder Content for Your Bibliography},
+  author = {Sample, Charlie and Demo, Diana},
+  booktitle = {Proceedings of the International Conference on Examples},
+  year = {2022},
+  pages = {1--10},
+}
+
+@online{webexample2024,
+  title = {This Website Does Not Actually Exist},
+  author = {{Example Organization}},
+  year = {2024},
+  url = {https://example.com/fake-page},
+}
diff --git a/packages/preview/bean-upm/0.1.0/thumbnail.png b/packages/preview/bean-upm/0.1.0/thumbnail.png
new file mode 100644
index 0000000000..01f7faafa5
Binary files /dev/null and b/packages/preview/bean-upm/0.1.0/thumbnail.png differ
diff --git a/packages/preview/bean-upm/0.1.0/typst.toml b/packages/preview/bean-upm/0.1.0/typst.toml
new file mode 100644
index 0000000000..d2728ffbaa
--- /dev/null
+++ b/packages/preview/bean-upm/0.1.0/typst.toml
@@ -0,0 +1,16 @@
+[package]
+name = "bean-upm"
+version = "0.1.0"
+entrypoint = "src/lib.typ"
+authors = ["Tikitikitikidesuka"]
+license = "MIT"
+description = "Universidad Politécnica de Madrid thesis/report template"
+repository = "https://github.com/Tikitikitikidesuka/typst-upm-report"
+keywords = ["thesis", "report", "upm"]
+categories = ["thesis", "report"]
+exclude = ["template/main.pdf"]
+
+[template]
+path = "template"
+entrypoint = "main.typ"
+thumbnail = "thumbnail.png"
\ No newline at end of file