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