From 9db231b18e156b7a8a9aba7142ed8d3004ca61a4 Mon Sep 17 00:00:00 2001 From: Hananoshika Yomaru Date: Mon, 18 May 2026 22:33:20 -0700 Subject: [PATCH] Update project configuration and documentation: set version in package.json, enhance spec.md with canvas feature details, add credits URL in zola.toml, and improve footer layout in base.html. Remove unused static files including 404.html, index.html, main.css, robots.txt, site.webmanifest, and sitemap.xml. --- LICENSE | 21 + content/credits.md | 4 + data/credits.json | 82 ++ data/credits.types.ts | 34 + package.json | 1 + spec.md | 4 +- static/icons/social/ATTRIBUTION.md | 3 + static/icons/social/bluesky.svg | 19 + static/icons/social/discord.svg | 22 + static/icons/social/email.svg | 20 + static/icons/social/facebook.svg | 19 + static/icons/social/github.svg | 19 + static/icons/social/gitlab.svg | 19 + static/icons/social/instagram.svg | 21 + static/icons/social/linkedin.svg | 23 + static/icons/social/mastodon.svg | 20 + static/icons/social/medium.svg | 24 + static/icons/social/orcid.svg | 19 + static/icons/social/rss.svg | 21 + static/icons/social/scholar.svg | 20 + static/icons/social/substack.svg | 22 + static/icons/social/threads.svg | 19 + static/icons/social/tiktok.svg | 19 + static/icons/social/website.svg | 23 + static/icons/social/x.svg | 20 + static/icons/social/youtube.svg | 20 + themes/openfreebooks/sass/_credits.scss | 86 ++ themes/openfreebooks/sass/_layout.scss | 16 +- themes/openfreebooks/sass/main.scss | 1 + themes/openfreebooks/static/404.html | 65 -- themes/openfreebooks/static/index.html | 755 ------------------ themes/openfreebooks/static/main.css | 1 - themes/openfreebooks/static/robots.txt | 4 - themes/openfreebooks/static/site.webmanifest | 19 - themes/openfreebooks/static/sitemap.xml | 6 - themes/openfreebooks/templates/base.html | 7 +- themes/openfreebooks/templates/credits.html | 16 + .../templates/macros/social-icons.html | 59 +- .../partials/contributors-block.html | 2 +- .../templates/partials/credits-content.html | 68 ++ .../partials/icons/social/bluesky.html | 11 + .../partials/icons/social/discord.html | 14 + .../partials/icons/social/email.html | 12 + .../partials/icons/social/facebook.html | 11 + .../partials/icons/social/github.html | 11 + .../partials/icons/social/gitlab.html | 11 + .../partials/icons/social/instagram.html | 13 + .../partials/icons/social/linkedin.html | 15 + .../partials/icons/social/mastodon.html | 12 + .../partials/icons/social/medium.html | 16 + .../partials/icons/social/orcid.html | 11 + .../templates/partials/icons/social/rss.html | 13 + .../partials/icons/social/scholar.html | 12 + .../partials/icons/social/substack.html | 14 + .../partials/icons/social/threads.html | 11 + .../partials/icons/social/tiktok.html | 11 + .../partials/icons/social/website.html | 15 + .../templates/partials/icons/social/x.html | 12 + .../partials/icons/social/youtube.html | 12 + zola.toml | 1 + 60 files changed, 986 insertions(+), 895 deletions(-) create mode 100644 LICENSE create mode 100644 content/credits.md create mode 100644 data/credits.json create mode 100644 data/credits.types.ts create mode 100644 static/icons/social/ATTRIBUTION.md create mode 100644 static/icons/social/bluesky.svg create mode 100644 static/icons/social/discord.svg create mode 100644 static/icons/social/email.svg create mode 100644 static/icons/social/facebook.svg create mode 100644 static/icons/social/github.svg create mode 100644 static/icons/social/gitlab.svg create mode 100644 static/icons/social/instagram.svg create mode 100644 static/icons/social/linkedin.svg create mode 100644 static/icons/social/mastodon.svg create mode 100644 static/icons/social/medium.svg create mode 100644 static/icons/social/orcid.svg create mode 100644 static/icons/social/rss.svg create mode 100644 static/icons/social/scholar.svg create mode 100644 static/icons/social/substack.svg create mode 100644 static/icons/social/threads.svg create mode 100644 static/icons/social/tiktok.svg create mode 100644 static/icons/social/website.svg create mode 100644 static/icons/social/x.svg create mode 100644 static/icons/social/youtube.svg create mode 100644 themes/openfreebooks/sass/_credits.scss delete mode 100644 themes/openfreebooks/static/404.html delete mode 100644 themes/openfreebooks/static/index.html delete mode 100644 themes/openfreebooks/static/main.css delete mode 100644 themes/openfreebooks/static/robots.txt delete mode 100644 themes/openfreebooks/static/site.webmanifest delete mode 100644 themes/openfreebooks/static/sitemap.xml create mode 100644 themes/openfreebooks/templates/credits.html create mode 100644 themes/openfreebooks/templates/partials/credits-content.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/bluesky.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/discord.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/email.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/facebook.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/github.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/gitlab.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/instagram.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/linkedin.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/mastodon.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/medium.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/orcid.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/rss.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/scholar.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/substack.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/threads.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/tiktok.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/website.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/x.html create mode 100644 themes/openfreebooks/templates/partials/icons/social/youtube.html diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0d461e1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Open Free Books contributors + +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/content/credits.md b/content/credits.md new file mode 100644 index 0000000..a4f01c2 --- /dev/null +++ b/content/credits.md @@ -0,0 +1,4 @@ ++++ +title = "Credits" +template = "credits.html" ++++ diff --git a/data/credits.json b/data/credits.json new file mode 100644 index 0000000..7726dce --- /dev/null +++ b/data/credits.json @@ -0,0 +1,82 @@ +{ + "intro": "Open Free Books uses the open source libraries below (in alphabetical order—we try!).", + "contributors_note": "Textbook authors and maintainers are listed on the homepage.", + "project": { + "name": "Open Free Books", + "version": "0.0.1", + "license": "MIT", + "license_url": "https://github.com/hananoshikayomaru/openfreebooks/blob/main/LICENSE", + "copyright": "Copyright (c) 2026 Open Free Books contributors", + "url": "https://openfreebooks.org" + }, + "libraries": [ + { + "name": "Bun", + "version": "1.3.10", + "license": "MIT", + "license_url": "https://github.com/oven-sh/bun/blob/main/LICENSE.md", + "copyright": "Copyright (c) Oven-sh", + "url": "https://bun.sh" + }, + { + "name": "Sass", + "version": "1.89.x", + "license": "MIT", + "license_url": "https://github.com/sass/dart-sass/blob/main/LICENSE", + "copyright": "Copyright (c) Google Inc. and contributors", + "url": "https://sass-lang.com" + }, + { + "name": "Solid.js", + "version": "1.9.13", + "license": "MIT", + "license_url": "https://github.com/solidjs/solid/blob/main/LICENSE", + "copyright": "Copyright (c) 2016-2025 Ryan Carniato", + "url": "https://www.solidjs.com" + }, + { + "name": "TypeScript", + "version": "5.9.3", + "license": "Apache License 2.0", + "license_url": "https://github.com/microsoft/TypeScript/blob/main/LICENSE.txt", + "copyright": "Copyright (c) Microsoft Corporation", + "url": "https://www.typescriptlang.org" + }, + { + "name": "Vite", + "version": "6.4.2", + "license": "MIT", + "license_url": "https://github.com/vitejs/vite/blob/main/LICENSE", + "copyright": "Copyright (c) 2019-present VoidZero Inc. and Vite contributors", + "url": "https://vite.dev" + }, + { + "name": "vite-plugin-solid", + "version": "2.11.12", + "license": "MIT", + "license_url": "https://github.com/solidjs/vite-plugin-solid/blob/main/LICENSE", + "copyright": "Copyright (c) 2021-present SolidJS contributors", + "url": "https://github.com/solidjs/vite-plugin-solid" + }, + { + "name": "Zola", + "version": "0.22.1", + "license": "MIT", + "license_url": "https://github.com/getzola/zola/blob/master/LICENSE", + "copyright": "Copyright (c) 2017-present Vincent Prouillet and contributors", + "url": "https://www.getzola.org" + } + ], + "hosting": [ + { + "name": "Cloudflare", + "url": "https://www.cloudflare.com", + "note": "Static site hosting, CDN, and deploy (Workers & Wrangler)" + }, + { + "name": "GitHub", + "url": "https://github.com/hananoshikayomaru/openfreebooks", + "note": "Code hosting" + } + ] +} diff --git a/data/credits.types.ts b/data/credits.types.ts new file mode 100644 index 0000000..d1f7946 --- /dev/null +++ b/data/credits.types.ts @@ -0,0 +1,34 @@ +/** Credits page data (`data/credits.json`). */ + +export interface CreditProject { + name: string; + version: string; + license: string; + license_url: string; + copyright: string; + url?: string; +} + +export interface CreditLibrary { + name: string; + version: string; + license: string; + license_url?: string; + copyright: string; + url: string; +} + +export interface CreditHosting { + name: string; + version?: string; + url: string; + note: string; +} + +export interface CreditsFile { + intro: string; + contributors_note: string; + project: CreditProject; + libraries: CreditLibrary[]; + hosting: CreditHosting[]; +} diff --git a/package.json b/package.json index 14f2c1b..c005949 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "openfreebooks", + "version": "0.0.1", "private": true, "type": "module", "scripts": { diff --git a/spec.md b/spec.md index f1f5ee8..2faf149 100644 --- a/spec.md +++ b/spec.md @@ -4,4 +4,6 @@ this project is free internet textbooks for elementary schools to university stu this project is build using zola. interactivity by solid js. deployed to cloudflare. -canvas feature use jsoncanvas standard by Obsidian. \ No newline at end of file +canvas feature use [jsoncanvas](https://jsoncanvas.org/spec/1.0/) standard by Obsidian. Viewer is [JSON canvas viewer](https://github.com/Hesprs/JSON-Canvas-Viewer). + +not markdown, html based. but in every page, we should have a copy as md button using [defuddle](https://github.com/kepano/defuddle). \ No newline at end of file diff --git a/static/icons/social/ATTRIBUTION.md b/static/icons/social/ATTRIBUTION.md new file mode 100644 index 0000000..0e2cfab --- /dev/null +++ b/static/icons/social/ATTRIBUTION.md @@ -0,0 +1,3 @@ +Social icons are from [Tabler Icons](https://tabler.io/icons) ([MIT License](https://github.com/tabler/tabler-icons/blob/master/LICENSE)). + +Source: https://github.com/tabler/tabler-icons/tree/main/icons/outline diff --git a/static/icons/social/bluesky.svg b/static/icons/social/bluesky.svg new file mode 100644 index 0000000..dc04b21 --- /dev/null +++ b/static/icons/social/bluesky.svg @@ -0,0 +1,19 @@ + + + + diff --git a/static/icons/social/discord.svg b/static/icons/social/discord.svg new file mode 100644 index 0000000..a992400 --- /dev/null +++ b/static/icons/social/discord.svg @@ -0,0 +1,22 @@ + + + + + + + diff --git a/static/icons/social/email.svg b/static/icons/social/email.svg new file mode 100644 index 0000000..2e51946 --- /dev/null +++ b/static/icons/social/email.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/static/icons/social/facebook.svg b/static/icons/social/facebook.svg new file mode 100644 index 0000000..c57aee6 --- /dev/null +++ b/static/icons/social/facebook.svg @@ -0,0 +1,19 @@ + + + + diff --git a/static/icons/social/github.svg b/static/icons/social/github.svg new file mode 100644 index 0000000..513c9bd --- /dev/null +++ b/static/icons/social/github.svg @@ -0,0 +1,19 @@ + + + + diff --git a/static/icons/social/gitlab.svg b/static/icons/social/gitlab.svg new file mode 100644 index 0000000..d96bdf4 --- /dev/null +++ b/static/icons/social/gitlab.svg @@ -0,0 +1,19 @@ + + + + diff --git a/static/icons/social/instagram.svg b/static/icons/social/instagram.svg new file mode 100644 index 0000000..d69523e --- /dev/null +++ b/static/icons/social/instagram.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/static/icons/social/linkedin.svg b/static/icons/social/linkedin.svg new file mode 100644 index 0000000..8318421 --- /dev/null +++ b/static/icons/social/linkedin.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/static/icons/social/mastodon.svg b/static/icons/social/mastodon.svg new file mode 100644 index 0000000..54ac596 --- /dev/null +++ b/static/icons/social/mastodon.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/static/icons/social/medium.svg b/static/icons/social/medium.svg new file mode 100644 index 0000000..5f0b934 --- /dev/null +++ b/static/icons/social/medium.svg @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/static/icons/social/orcid.svg b/static/icons/social/orcid.svg new file mode 100644 index 0000000..506d775 --- /dev/null +++ b/static/icons/social/orcid.svg @@ -0,0 +1,19 @@ + + + + diff --git a/static/icons/social/rss.svg b/static/icons/social/rss.svg new file mode 100644 index 0000000..485d579 --- /dev/null +++ b/static/icons/social/rss.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/static/icons/social/scholar.svg b/static/icons/social/scholar.svg new file mode 100644 index 0000000..2845625 --- /dev/null +++ b/static/icons/social/scholar.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/static/icons/social/substack.svg b/static/icons/social/substack.svg new file mode 100644 index 0000000..e673025 --- /dev/null +++ b/static/icons/social/substack.svg @@ -0,0 +1,22 @@ + + + + + + + diff --git a/static/icons/social/threads.svg b/static/icons/social/threads.svg new file mode 100644 index 0000000..d6c0b9c --- /dev/null +++ b/static/icons/social/threads.svg @@ -0,0 +1,19 @@ + + + + diff --git a/static/icons/social/tiktok.svg b/static/icons/social/tiktok.svg new file mode 100644 index 0000000..1481298 --- /dev/null +++ b/static/icons/social/tiktok.svg @@ -0,0 +1,19 @@ + + + + diff --git a/static/icons/social/website.svg b/static/icons/social/website.svg new file mode 100644 index 0000000..9803590 --- /dev/null +++ b/static/icons/social/website.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/static/icons/social/x.svg b/static/icons/social/x.svg new file mode 100644 index 0000000..3f39f78 --- /dev/null +++ b/static/icons/social/x.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/static/icons/social/youtube.svg b/static/icons/social/youtube.svg new file mode 100644 index 0000000..e636729 --- /dev/null +++ b/static/icons/social/youtube.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/themes/openfreebooks/sass/_credits.scss b/themes/openfreebooks/sass/_credits.scss new file mode 100644 index 0000000..2e35efd --- /dev/null +++ b/themes/openfreebooks/sass/_credits.scss @@ -0,0 +1,86 @@ +.credits-page { + padding: 54px 0 72px; + border-top: 1px solid var(--line); +} + +.credits-prose { + max-width: var(--prose-width); +} + +.credits-lead, +.credits-contributors-note, +.credits-section-intro { + margin: 0 0 1rem; + color: var(--soft-ink); + font-size: 1.05rem; + line-height: 1.72; +} + +.credits-contributors-note a, +.credits-entry-name a, +.credits-entry-license a { + color: var(--accent); + font-weight: 600; + text-decoration: none; +} + +.credits-contributors-note a:hover, +.credits-contributors-note a:focus-visible, +.credits-entry-name a:hover, +.credits-entry-name a:focus-visible, +.credits-entry-license a:hover, +.credits-entry-license a:focus-visible { + text-decoration: underline; + text-underline-offset: 3px; +} + +.credits-block { + margin-top: 40px; +} + +.credits-section-title { + margin: 0 0 16px; + font-family: var(--font-heading); + font-size: clamp(1.35rem, 2.2vw, 1.85rem); + font-weight: 400; + line-height: 1.2; +} + +.credits-entry { + margin: 0 0 28px; + padding-bottom: 28px; + border-bottom: 1px solid var(--line); +} + +.credits-block .credits-entry:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; +} + +.credits-entry-name { + margin: 0 0 8px; + font-family: var(--font-heading); + font-size: 1.25rem; + font-weight: 400; + line-height: 1.25; +} + +.credits-entry-name a { + color: var(--ink); +} + +.credits-entry-version, +.credits-entry-license, +.credits-entry-copyright, +.credits-entry-note { + margin: 0 0 6px; + color: var(--soft-ink); + font-size: 0.98rem; + line-height: 1.6; +} + +.credits-entry-copyright:last-child, +.credits-entry-note:last-child { + margin-bottom: 0; +} diff --git a/themes/openfreebooks/sass/_layout.scss b/themes/openfreebooks/sass/_layout.scss index 66a8cc6..ee548b7 100644 --- a/themes/openfreebooks/sass/_layout.scss +++ b/themes/openfreebooks/sass/_layout.scss @@ -49,9 +49,21 @@ section.hero { .footer-inner { display: flex; flex-wrap: wrap; - justify-content: space-between; align-items: baseline; - gap: 12px 20px; + gap: 12px 24px; +} + +.footer-copy { + flex: 1 1 16rem; + min-width: min(100%, 16rem); +} + +.footer-links { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 12px 24px; + flex-shrink: 0; } .footer-link { diff --git a/themes/openfreebooks/sass/main.scss b/themes/openfreebooks/sass/main.scss index 96aafe4..d3432f6 100644 --- a/themes/openfreebooks/sass/main.scss +++ b/themes/openfreebooks/sass/main.scss @@ -4,3 +4,4 @@ @import "components"; @import "why-sections"; @import "contributors"; +@import "credits"; diff --git a/themes/openfreebooks/static/404.html b/themes/openfreebooks/static/404.html deleted file mode 100644 index 2925e02..0000000 --- a/themes/openfreebooks/static/404.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - Page not found | Open Free Books - - - - - - - - - - - - - - - - - - - - -
- -
-
-
-

Page not found

-

That page is not in the catalog yet. Try the homepage or browse when books are published.

- -
-
-
- -
- - - - - - - diff --git a/themes/openfreebooks/static/index.html b/themes/openfreebooks/static/index.html deleted file mode 100644 index 7456d95..0000000 --- a/themes/openfreebooks/static/index.html +++ /dev/null @@ -1,755 +0,0 @@ - - - - - - Open Free Books - - - - - - - - - - - - - - - - - - - - -
- -
-
-
-

Open textbooks. Free to read. Open to improve.

-

- High-quality learning materials for elementary school through university — on the web, at no cost. -

-
    -
  • Free means the whole book, for everyone — read it all online without paywalls.
  • -
  • Open means open source — anyone can fix a typo, add a chapter, or fork a book on GitHub.
  • -
- -
-
-
- -
- -
-
-
- - -
-
-

The problem

-

Textbook fees hit families hard

-

- In many countries, families pay hundreds of dollars per child each year for printed textbooks — - on top of tuition, devices, and supplies. When money is tight, students share worn copies, skip - buying books, or fall behind before the term begins. -

-

- That cost is not a small inconvenience. It is a barrier to showing up prepared. Open Free Books - exists so every learner can start the year with complete materials, not a receipt. -

-
-
-
- -
-
-
- - -
-
-

The medium

-

Long live the web — not the PDF

-

- Paper textbooks are fixed: one layout, one edition, no room to fix a typo until the next print run. - Most “digital” versions are the same pages exported to PDF — still static, still hard to search, - still impossible to embed a simulation or a live diagram. -

-

- HTML on the open web is different. Chapters can link to sources, resize for any screen, - include interactive figures, and improve over time. The book becomes something you use — not something - you only carry. -

-
-
-
- -
-
-
- - -
-
-

People & books

-

Replace textbooks, not teachers

-

- A great teacher — whether in person or, someday, assisted by thoughtful tools — still sets pace, - asks hard questions, and notices when a student is stuck. That relationship is not what we are - trying to automate. -

-

- Textbooks are different. They are reference and structure: explanations, exercises, diagrams. - Those can be free, forkable, and kept current on the web so teachers spend less - time hunting permissions and more time teaching. -

-
-
-
- -
-
-
- - -
-
-

Agency

-

Do not outsource your learning

-

- Finishing a chapter is not the same as understanding it. Skimming for answers, copying worked - solutions, or rushing to the end leaves gaps that show up on the next test — and in the years after. -

-

- Read slowly. Try the problems before you peek at hints. Sit with confusion long enough to name what - you do not get. The textbook is a guide; the thinking still has to be yours. That habit - is what school is really training, whether the subject is algebra or history. -

-
-
-
- -
-
-
- - -
-
-

Planet

-

Open textbooks are gentler on the Earth

-

- Core curriculum changes slowly. Newton’s laws, the structure of a cell, and how fractions work do not - need a new AI run every September. Regenerating the same chapter thousands of times burns electricity - in data centers — for text that could have been written once and shared openly. -

-

- One carefully reviewed book, published on the web for everyone, means less redundant - compute, less e-waste from disposable PDFs, and fewer trucks moving heavy print runs. Students get - stable material they can trust; the environment gets less waste from doing the same work over and over. -

-
-
-
- -
-
-
- - -
-
-

Craft

-

Carefully crafted by brilliant people on Earth

-

- A textbook is not a bulk download. It is years of lectures distilled, diagrams redrawn until they - click, exercises tested in real classrooms, and arguments tightened by reviewers who care about - getting it right. -

-

- Open Free Books gathers that work from educators and researchers at institutions around the world — - people who have already spent their careers making hard ideas legible. We publish their care - openly so the next student inherits the best version, not a disposable draft. -

-
-
-
-

Contributors and partners from leading universities include

- - -
-
- - -
-
-

Catalog

-

Browse by subject

-
-
-

Mathematics

-

Coming soon

-

Algebra, calculus, statistics, and more — structured for self-study and classrooms.

-
-
-

Science

-

Coming soon

-

Physics, chemistry, biology, and earth science from introductory to advanced levels.

-
-
-

Humanities

-

Coming soon

-

History, literature, philosophy, and languages — readable, citable, and free to share.

-
-
-

Computing

-

Coming soon

-

Programming, computer science fundamentals, and practical skills for students and teachers.

-
-
-

Subject pages and full catalogs are on the roadmap. Contribute a book on GitHub.

-
-
- - - - - -
-
-

People

-

Contributors

-

- Open Free Books is written and maintained in the open. These are the people building and reviewing the textbooks. -

-
    - - -
  • - -
  • - -
- - - - -
- -
- - - -
-

Man Lung Yeung

- -

EdTech specialist / software engineer

- -
-
- -

- Education - BEng in Computer Science (HKUST) + BBA (HKUST) -

- - -
- Contributes -
    - -
  • Founder
  • - -
  • Math textbook
  • - -
  • Physics textbook
  • - -
  • Chemistry textbook
  • - -
-
- - -
-
- - -

- Want to contribute? Open a pull request on GitHub. -

-
-
- - -
- - - - - - - diff --git a/themes/openfreebooks/static/main.css b/themes/openfreebooks/static/main.css deleted file mode 100644 index 997df6b..0000000 --- a/themes/openfreebooks/static/main.css +++ /dev/null @@ -1 +0,0 @@ -:root{--ink: #1a1a1a;--soft-ink: #555;--muted: #767676;--accent: #9a6b2e;--line: #e8e8e8;--paper: #f5f4f1;--header-bg-scrolled: rgba(252, 252, 253, 0.9);--card-bg: rgba(255, 255, 255, 0.66);--card-border: rgba(26, 26, 26, 0.08);--shadow-soft: rgba(20, 20, 20, 0.04);--mono: "IBM Plex Mono", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--font-heading: "Instrument Serif", serif;--font-body: Inter, Arial, sans-serif;--prose-width: 68ch;--grain-svg: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.55'/%3E%3C/svg%3E")}[data-theme=dark]{--ink: #eceae4;--soft-ink: #b8b4ab;--muted: #8f8a80;--accent: #c4924a;--line: #3a3834;--paper: #1a1917;--header-bg-scrolled: rgba(26, 25, 23, 0.92);--card-bg: rgba(36, 34, 31, 0.72);--card-border: rgba(236, 234, 228, 0.1);--shadow-soft: rgba(0, 0, 0, 0.25)}@media (prefers-color-scheme: dark){:root:not([data-theme=light]){--ink: #eceae4;--soft-ink: #b8b4ab;--muted: #8f8a80;--accent: #c4924a;--line: #3a3834;--paper: #1a1917;--header-bg-scrolled: rgba(26, 25, 23, 0.92);--card-bg: rgba(36, 34, 31, 0.72);--card-border: rgba(236, 234, 228, 0.1);--shadow-soft: rgba(0, 0, 0, 0.25)}}body::before{content:"";position:fixed;inset:0;z-index:9999;pointer-events:none;opacity:.7;mix-blend-mode:multiply;background-image:var(--grain-svg);background-size:180px 180px}.contributor-dialog[open],.contributor-dialog[open] .contributor-dialog-panel{mix-blend-mode:normal}[data-theme=dark] body::before{opacity:.45;mix-blend-mode:soft-light}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) body::before{opacity:.45;mix-blend-mode:soft-light}}*{box-sizing:border-box}html{scroll-behavior:smooth}@media (prefers-reduced-motion: reduce){html{scroll-behavior:auto}}html,body{margin:0;padding:0;background:var(--paper);color:var(--ink);font-family:var(--font-body)}.container{width:min(1100px,92vw);margin:0 auto}main{min-height:50vh}section{padding:54px 0}section.hero{padding:0}.footer{border-top:1px solid var(--line);margin-top:45px;padding:20px 0 34px;color:var(--soft-ink);font-size:.84rem}.footer-inner{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:12px 20px}.footer-link{font-size:.78rem;color:var(--muted);text-decoration:none;letter-spacing:.02em}.footer-link:hover,.footer-link:focus-visible{color:var(--accent)}h1,h2,h3{margin:0;font-family:var(--font-heading);font-weight:400}.site-header{position:sticky;top:0;z-index:8;border-bottom:1px solid rgba(0,0,0,0);transition:background-color 320ms ease,border-color 320ms ease,box-shadow 320ms ease}.site-header.is-scrolled{backdrop-filter:blur(10px);background:var(--header-bg-scrolled);border-color:var(--line);box-shadow:0 8px 20px var(--shadow-soft)}.header-row{padding:24px 0;display:flex;justify-content:space-between;align-items:center;gap:20px;transition:padding 320ms ease}.site-header.is-scrolled .header-row{padding:13px 0}.brand{display:flex;align-items:center;gap:12px}.brand-name{font-family:var(--font-heading);font-weight:400;font-size:1.2rem;color:var(--ink);text-decoration:none}.brand-name:hover,.brand-name:focus-visible{color:var(--accent)}.header-actions{display:flex;align-items:center;gap:16px}.main-nav{display:flex;gap:26px}.main-nav a{color:var(--soft-ink);letter-spacing:.14em;text-transform:uppercase;font-size:.7rem;font-weight:700;font-family:var(--mono);text-decoration:none}.main-nav a:hover,.main-nav a:focus-visible{color:var(--accent)}.theme-toggle{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;margin:0;padding:0;border:1px solid var(--line);border-radius:8px;background:rgba(0,0,0,0);color:var(--ink);cursor:pointer;transition:background-color .2s ease,border-color .2s ease}.theme-toggle:hover{background:color-mix(in srgb, var(--accent) 10%, rgba(0,0,0,0));border-color:color-mix(in srgb, var(--accent) 35%, var(--line))}.theme-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.nav-burger{display:none;flex-direction:column;justify-content:center;align-items:center;gap:5px;width:32px;height:32px;margin:0;padding:0;border:0;border-radius:8px;background:rgba(0,0,0,0);color:var(--ink);cursor:pointer;position:relative;z-index:10003;transition:background-color .2s ease}.nav-burger:hover{background:color-mix(in srgb, var(--accent) 12%, rgba(0,0,0,0))}.nav-burger:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.nav-burger-line{display:block;width:22px;height:2px;border-radius:1px;background:currentColor;transition:transform .32s ease,opacity .24s ease}.site-header.nav-is-open .nav-burger-line:nth-child(1){transform:translateY(7px) rotate(45deg)}.site-header.nav-is-open .nav-burger-line:nth-child(2){opacity:0}.site-header.nav-is-open .nav-burger-line:nth-child(3){transform:translateY(-7px) rotate(-45deg)}.nav-backdrop{display:none}.mobile-nav-panel{display:none}.hero{position:relative;min-height:min(88vh,720px);display:flex;flex-direction:column;padding:0}.hero .container{flex:1;display:flex;flex-direction:column;justify-content:center;padding-block:clamp(2rem,6vh,5rem)}.hero h1{max-width:860px;font-size:clamp(2.2rem,5.2vw,4.2rem);line-height:1.08}.hero-lead{max-width:680px;margin:24px 0 16px;color:var(--soft-ink);font-size:clamp(1.05rem,1.9vw,1.35rem);line-height:1.55}.hero-points{max-width:680px;margin:0 0 32px;padding:0;list-style:none;color:var(--soft-ink);font-size:1.02rem;line-height:1.65}.hero-points li{margin-bottom:.5rem;padding-left:1.25rem;position:relative}.hero-points li::before{content:"—";position:absolute;left:0;color:var(--accent)}.hero-actions{display:flex;flex-wrap:wrap;gap:20px;align-items:center}.button{display:inline-flex;align-items:center;justify-content:center;border-radius:4px;padding:16px 32px;text-decoration:none;font-weight:700;font-size:.93rem;letter-spacing:.02em;border:1px solid rgba(0,0,0,0);transition:transform 200ms ease,box-shadow 200ms ease,color 200ms ease}.button-primary{background:var(--accent);color:#fff}.button-primary:hover{transform:translateY(-1px);box-shadow:0 10px 24px color-mix(in srgb, var(--accent) 35%, rgba(0,0,0,0))}.button-secondary{color:var(--ink);border-color:rgba(0,0,0,0);background:rgba(0,0,0,0);padding-left:0;padding-right:0;border-radius:0}.button-secondary:hover{color:var(--accent)}.section-kicker{margin-bottom:8px;font-size:.72rem;letter-spacing:.16em;color:var(--accent);text-transform:uppercase;font-weight:700;font-family:var(--mono)}.section-title{font-size:clamp(1.75rem,3.1vw,2.8rem);margin-bottom:24px}.section-note{margin-top:14px;color:var(--muted);font-size:.88rem}.work-grid{display:grid;gap:18px;grid-template-columns:repeat(2, minmax(0, 1fr))}.work-card{background:var(--card-bg);border:1px solid var(--card-border);border-radius:0;overflow:hidden;padding:24px;transition:transform 350ms ease,opacity 500ms ease,translate 500ms ease;opacity:0;translate:0 20px}.work-card.is-inview{opacity:1;translate:0 0}.work-card:hover{transform:scale(1.01)}.work-card h3{margin:0 0 12px;font-size:clamp(1.4rem,2vw,1.85rem);line-height:1.2}.work-card p{color:var(--soft-ink);margin:0;font-size:1.02rem;line-height:1.7}.card-subtitle{font-style:italic;color:var(--muted);font-size:.98rem;margin-bottom:12px}.marquee-shell{margin:0;padding:0}.marquee{overflow:hidden;white-space:nowrap;width:100vw;margin-left:calc(-50vw + 50%);padding:14px 0}.marquee-track{display:inline-flex;align-items:center;animation:marquee-slide 32s linear infinite}.marquee-text{font-family:var(--font-heading);font-style:italic;font-weight:400;color:color-mix(in srgb, var(--ink) 72%, rgba(0,0,0,0));font-size:clamp(1.25rem,2.3vw,1.65rem);line-height:1.22;user-select:none;white-space:nowrap;display:inline-block;padding-right:3rem}.marquee-line{height:1px;background:linear-gradient(90deg, color-mix(in srgb, var(--accent) 45%, rgba(0,0,0,0)) 0%, color-mix(in srgb, var(--accent) 20%, rgba(0,0,0,0)) 100%)}@keyframes marquee-slide{from{transform:translateX(0)}to{transform:translateX(-33.333333%)}}@media (max-width: 900px){.work-grid{grid-template-columns:1fr}}@media (max-width: 467px){.nav-burger{display:inline-flex;margin-left:auto}.header-actions .main-nav{display:none}.site-header.nav-is-open{z-index:10000;background-color:var(--paper);border-bottom-color:var(--line);box-shadow:0 8px 20px var(--shadow-soft);backdrop-filter:none}.nav-backdrop{display:block;position:fixed;inset:0;z-index:10001;background:rgba(22,22,22,.48);backdrop-filter:blur(10px);opacity:0;pointer-events:none;transition:opacity .3s ease}.site-header.nav-is-open .nav-backdrop{opacity:1;pointer-events:auto}.mobile-nav-panel{position:fixed;inset:0;z-index:10002;display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;gap:0;padding:96px 28px 40px;margin:0;background-color:var(--paper);opacity:0;visibility:hidden;pointer-events:none;transition:none}.mobile-nav-panel::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.7;mix-blend-mode:multiply;background-image:var(--grain-svg);background-size:180px 180px}.site-header.nav-is-open .mobile-nav-panel{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .3s ease,visibility .3s ease}.mobile-nav-panel a{position:relative;z-index:1;color:var(--soft-ink);letter-spacing:.14em;text-transform:uppercase;font-size:1.05rem;font-weight:700;font-family:var(--mono);text-decoration:none;padding:14px 0;width:100%}.mobile-nav-panel a:hover{color:var(--accent)}}@media (prefers-reduced-motion: reduce){.marquee-track{animation:none}.work-card{opacity:1;translate:0 0;transition:none}}@media (hover: none),(pointer: coarse){.marquee-track{animation-duration:48s}}.why-section{padding:64px 0;border-top:1px solid var(--line)}.why-row{display:grid;grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);gap:clamp(32px,5vw,56px);align-items:center}.why-row--art-end .why-art{order:2}.why-row--art-end .why-copy{order:1}.why-art{display:flex;justify-content:center;align-items:center;opacity:0;translate:0 20px;transition:opacity 500ms ease,translate 500ms ease}.why-art.is-inview{opacity:1;translate:0 0}.why-art svg{width:min(100%,280px);height:auto;display:block}.why-copy{max-width:var(--prose-width);opacity:0;translate:0 20px;transition:opacity 500ms ease,translate 500ms ease}.why-copy.is-inview{opacity:1;translate:0 0}.why-copy .section-title{margin-bottom:16px}.why-copy p{margin:0 0 1rem;color:var(--soft-ink);font-size:1.05rem;line-height:1.72}.why-copy p:last-child{margin-bottom:0}.why-copy strong{color:var(--ink);font-weight:600}.why-section--community .why-craft-logos-wrap{overflow:hidden;opacity:0;translate:0 20px;transition:opacity 500ms ease,translate 500ms ease}.why-section--community .why-craft-logos-wrap.is-inview{opacity:1;translate:0 0}.university-logos-label{margin:0 0 24px;text-align:center;font-family:var(--mono);font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}.university-carousel{display:flex;flex-direction:column;gap:12px;width:100vw;margin-left:calc(-50vw + 50%);overflow:hidden}.university-carousel-row{overflow:hidden;mask-image:linear-gradient(90deg, rgba(0,0,0,0) 0%, #000 6%, #000 94%, rgba(0,0,0,0) 100%)}.university-carousel-track{display:flex;width:max-content;animation:university-carousel-forward 52s linear infinite}.university-carousel-row--reverse .university-carousel-track{animation-name:university-carousel-reverse;animation-duration:58s}.university-carousel-row--slow .university-carousel-track{animation-duration:64s}.university-carousel-group{display:flex;flex-shrink:0;align-items:center;gap:12px;margin:0;padding:0 6px;list-style:none}@keyframes university-carousel-forward{from{transform:translateX(0)}to{transform:translateX(-50%)}}@keyframes university-carousel-reverse{from{transform:translateX(-50%)}to{transform:translateX(0)}}.university-logo{display:flex;align-items:center;justify-content:center;min-height:56px;padding:10px 12px;background:var(--card-bg);border:1px solid var(--card-border)}.university-logo svg{width:108px;height:auto;display:block;color:var(--ink)}.university-logo--mit{color:#a31f34}[data-theme=dark] .university-logo--mit{color:#e85a6f}.university-logo--harvard{color:#a51c30}[data-theme=dark] .university-logo--harvard{color:#e88a96}.university-logo--stanford{color:#8c1515}[data-theme=dark] .university-logo--stanford{color:#e88a8a}.university-logo--berkeley{color:#003262}[data-theme=dark] .university-logo--berkeley{color:#6a9fd4}.university-logo--caltech{color:#ff6c0c}[data-theme=dark] .university-logo--caltech{color:#f5a623}.university-logo--princeton{color:#e77500}[data-theme=dark] .university-logo--princeton{color:#f0a040}.university-logo--yale{color:#00356b}[data-theme=dark] .university-logo--yale{color:#6a9fd4}.university-logo--columbia{color:#003865}[data-theme=dark] .university-logo--columbia{color:#7eb3e8}.university-logo--cornell{color:#b31b1b}[data-theme=dark] .university-logo--cornell{color:#e85a6f}.university-logo--cmu{color:#c41230}[data-theme=dark] .university-logo--cmu{color:#e87888}.university-logo--oxford{color:#002147}[data-theme=dark] .university-logo--oxford{color:#7eb3e8}.university-logo--cambridge{color:#0072cf}[data-theme=dark] .university-logo--cambridge{color:#6ab0f0}.university-logo--imperial{color:#003e74}[data-theme=dark] .university-logo--imperial{color:#6a9fd4}.university-logo--lse{color:#e41f13}[data-theme=dark] .university-logo--lse{color:#f07870}.university-logo--eth{color:#1f407a}[data-theme=dark] .university-logo--eth{color:#6a9fd4}.university-logo--toronto{color:#002a5c}[data-theme=dark] .university-logo--toronto{color:#6a9fd4}.university-logo--mcgill{color:#ed1b2f}[data-theme=dark] .university-logo--mcgill{color:#f07888}.university-logo--hku{color:#006747}[data-theme=dark] .university-logo--hku{color:#3cb88a}.university-logo--hkust{color:#036}[data-theme=dark] .university-logo--hkust{color:#6a9fd4}.university-logo--cuhk{color:#7b2d8e}[data-theme=dark] .university-logo--cuhk{color:#c49ae0}.university-logo--nus{color:#ef7c00}[data-theme=dark] .university-logo--nus{color:#f5a623}.university-logo--tsinghua{color:#82318e}[data-theme=dark] .university-logo--tsinghua{color:#c49ae0}.university-logo--pku{color:#94070a}[data-theme=dark] .university-logo--pku{color:#e87878}.university-logo--utokyo{color:#003f87}[data-theme=dark] .university-logo--utokyo{color:#6a9fd4}.university-logo--anu{color:#c4a337}[data-theme=dark] .university-logo--anu{color:#e8c860}.university-logo--melbourne{color:#094183}[data-theme=dark] .university-logo--melbourne{color:#6a9fd4}.university-logo--iitb{color:#036}[data-theme=dark] .university-logo--iitb{color:#6a9fd4}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .university-logo--mit{color:#e85a6f}:root:not([data-theme=light]) .university-logo--harvard{color:#e88a96}:root:not([data-theme=light]) .university-logo--stanford{color:#e88a8a}:root:not([data-theme=light]) .university-logo--berkeley{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--caltech{color:#f5a623}:root:not([data-theme=light]) .university-logo--princeton{color:#f0a040}:root:not([data-theme=light]) .university-logo--yale{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--columbia{color:#7eb3e8}:root:not([data-theme=light]) .university-logo--cornell{color:#e85a6f}:root:not([data-theme=light]) .university-logo--cmu{color:#e87888}:root:not([data-theme=light]) .university-logo--oxford{color:#7eb3e8}:root:not([data-theme=light]) .university-logo--cambridge{color:#6ab0f0}:root:not([data-theme=light]) .university-logo--imperial{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--lse{color:#f07870}:root:not([data-theme=light]) .university-logo--eth{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--toronto{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--mcgill{color:#f07888}:root:not([data-theme=light]) .university-logo--hku{color:#3cb88a}:root:not([data-theme=light]) .university-logo--hkust{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--cuhk{color:#c49ae0}:root:not([data-theme=light]) .university-logo--nus{color:#f5a623}:root:not([data-theme=light]) .university-logo--tsinghua{color:#c49ae0}:root:not([data-theme=light]) .university-logo--pku{color:#e87878}:root:not([data-theme=light]) .university-logo--utokyo{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--anu{color:#e8c860}:root:not([data-theme=light]) .university-logo--melbourne{color:#6a9fd4}:root:not([data-theme=light]) .university-logo--iitb{color:#6a9fd4}}@media (max-width: 900px){.why-row,.why-row--art-end{grid-template-columns:1fr}.why-row--art-end .why-art,.why-row--art-end .why-copy{order:unset}.why-art svg{width:min(100%,220px)}}@media (prefers-reduced-motion: reduce){.why-art,.why-copy,.why-section--community .why-craft-logos-wrap{opacity:1;translate:0 0;transition:none}.university-carousel-track{animation:none;flex-wrap:wrap;width:100%;justify-content:center}.university-carousel-row{mask-image:none}.university-carousel-group[aria-hidden=true]{display:none}.university-carousel{width:100%;margin-left:0}}.why-section--community{--community-block-gap: 72px}.why-section--community .why-craft-logos-wrap{margin-top:var(--community-block-gap)}.why-section--community .community-contributors{margin-top:var(--community-block-gap);padding-bottom:12px}.contributors-intro{max-width:var(--prose-width);margin:0 0 24px;color:var(--soft-ink);font-size:1.05rem;line-height:1.72}.contributors-avatar-grid{display:flex;flex-wrap:wrap;gap:4px;margin:0;padding:0;list-style:none}.contributors-avatar-item{opacity:0;translate:0 12px;transition:opacity 400ms ease,translate 400ms ease}.contributors-avatar-item.is-inview{opacity:1;translate:0 0}.contributor-avatar-btn{display:block;margin:0;padding:0;border:2px solid rgba(0,0,0,0);border-radius:50%;background:none;cursor:pointer;line-height:0;transition:border-color 160ms ease,transform 160ms ease}.contributor-avatar-btn:hover,.contributor-avatar-btn:focus-visible{border-color:var(--accent);transform:translateY(-2px);outline:none}.contributor-avatar-img,.contributor-avatar-fallback{display:block;width:48px;height:48px;border-radius:50%}.contributor-avatar-img{object-fit:cover;border:1px solid var(--card-border);background:var(--paper)}.contributor-avatar-fallback{display:flex;align-items:center;justify-content:center;background:var(--card-bg);border:1px solid var(--card-border);color:var(--accent);font-family:var(--font-heading);font-size:1.25rem;font-weight:400;text-transform:uppercase}.contributor-dialog{margin:auto;padding:0;border:none;max-width:min(92vw,440px);background-color:#f5f4f1;color:var(--ink);isolation:isolate}[data-theme=dark] .contributor-dialog{background-color:#1a1917}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .contributor-dialog{background-color:#1a1917}}.contributor-dialog::backdrop{background:rgba(26,26,26,.45)}[data-theme=dark] .contributor-dialog::backdrop{background:rgba(0,0,0,.62)}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .contributor-dialog::backdrop{background:rgba(0,0,0,.62)}}.contributor-dialog-panel{display:block;width:100%;box-sizing:border-box;position:relative;margin:0;padding:28px 28px 24px;border:1px solid var(--card-border);background-color:#f5f4f1;box-shadow:0 18px 48px var(--shadow-soft)}[data-theme=dark] .contributor-dialog-panel{background-color:#1a1917}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .contributor-dialog-panel{background-color:#1a1917}}.contributor-dialog-close{position:absolute;top:12px;right:12px;width:36px;height:36px;margin:0;padding:0;border:none;border-radius:50%;background:rgba(0,0,0,0);color:var(--muted);font-size:1.5rem;line-height:1;cursor:pointer}.contributor-dialog-close:hover,.contributor-dialog-close:focus-visible{color:var(--ink);background:var(--paper);outline:none}.contributor-dialog-header{display:flex;align-items:center;gap:18px;margin-bottom:18px;padding-right:28px}.contributor-dialog-avatar{flex-shrink:0;width:80px;height:80px;border-radius:50%;object-fit:cover;border:1px solid var(--card-border);background:var(--paper)}.contributor-dialog-name{margin:0 0 6px;font-family:var(--font-heading);font-size:clamp(1.35rem,2vw,1.75rem);font-weight:400;line-height:1.2}.contributor-dialog-job{margin:0;color:var(--accent);font-family:var(--mono);font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;font-weight:700}.contributor-dialog-meta,.contributor-dialog-contributions{margin:0 0 14px;color:var(--soft-ink);font-size:.98rem;line-height:1.65}.contributor-meta-label{display:block;margin-bottom:4px;font-family:var(--mono);font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:700}.contributor-contribution-list{margin:0;padding:0;list-style:none}.contributor-contribution-list li{position:relative;padding-left:1rem;margin-bottom:.35rem}.contributor-contribution-list li::before{content:"—";position:absolute;left:0;color:var(--accent)}.contributor-dialog-connect{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}.contributor-social-list{display:flex;flex-wrap:wrap;gap:10px;margin:8px 0 0;padding:0;list-style:none}.contributor-social-link{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border:1px solid var(--card-border);border-radius:50%;color:var(--ink);text-decoration:none;background:var(--paper);transition:border-color 160ms ease,color 160ms ease,transform 160ms ease}.contributor-social-link:hover,.contributor-social-link:focus-visible{border-color:var(--accent);color:var(--accent);transform:translateY(-1px);outline:none}.contributor-social-icon{display:block;flex-shrink:0}.why-section--community .section-note a{color:var(--accent)}.why-section--community .community-contributors .section-note{margin-top:28px}@media (prefers-reduced-motion: reduce){.contributors-avatar-item{opacity:1;translate:0 0;transition:none}.contributor-avatar-btn:hover,.contributor-avatar-btn:focus-visible{transform:none}} \ No newline at end of file diff --git a/themes/openfreebooks/static/robots.txt b/themes/openfreebooks/static/robots.txt deleted file mode 100644 index 5c2271f..0000000 --- a/themes/openfreebooks/static/robots.txt +++ /dev/null @@ -1,4 +0,0 @@ -User-agent: * -Disallow: -Allow: / -Sitemap: https://openfreebooks.org/sitemap.xml diff --git a/themes/openfreebooks/static/site.webmanifest b/themes/openfreebooks/static/site.webmanifest deleted file mode 100644 index 573ed77..0000000 --- a/themes/openfreebooks/static/site.webmanifest +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "Open Free Books", - "short_name": "OpenFreeBooks", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#9a6b2e", - "background_color": "#f5f4f1", - "display": "standalone" -} diff --git a/themes/openfreebooks/static/sitemap.xml b/themes/openfreebooks/static/sitemap.xml deleted file mode 100644 index e2bfb64..0000000 --- a/themes/openfreebooks/static/sitemap.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - https://openfreebooks.org/ - - diff --git a/themes/openfreebooks/templates/base.html b/themes/openfreebooks/templates/base.html index 312318c..ed30a7e 100644 --- a/themes/openfreebooks/templates/base.html +++ b/themes/openfreebooks/templates/base.html @@ -41,8 +41,11 @@ diff --git a/themes/openfreebooks/templates/credits.html b/themes/openfreebooks/templates/credits.html new file mode 100644 index 0000000..e9057d6 --- /dev/null +++ b/themes/openfreebooks/templates/credits.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block title %}Credits | {{ config.extra.site_title }}{% endblock title %} +{% block meta_description %} + +{% endblock meta_description %} + +{% block content %} +
+
+

Acknowledgements

+

{{ page.title }}

+ {% include "partials/credits-content.html" %} +
+
+{% endblock content %} diff --git a/themes/openfreebooks/templates/macros/social-icons.html b/themes/openfreebooks/templates/macros/social-icons.html index c69b076..2190ab1 100644 --- a/themes/openfreebooks/templates/macros/social-icons.html +++ b/themes/openfreebooks/templates/macros/social-icons.html @@ -26,66 +26,47 @@ {% endmacro %} {% macro social_icon(kind) %} - {% endmacro %} {% macro website_icon() %} - +{% include "partials/icons/social/website.html" %} {% endmacro %} diff --git a/themes/openfreebooks/templates/partials/contributors-block.html b/themes/openfreebooks/templates/partials/contributors-block.html index c7ee9e4..e262dd6 100644 --- a/themes/openfreebooks/templates/partials/contributors-block.html +++ b/themes/openfreebooks/templates/partials/contributors-block.html @@ -1,4 +1,4 @@ -{% set contributors_data = load_data(path="contributors.json", format="json") %} +{% set contributors_data = load_data(path="data/contributors.json", format="json") %}
diff --git a/themes/openfreebooks/templates/partials/credits-content.html b/themes/openfreebooks/templates/partials/credits-content.html new file mode 100644 index 0000000..f1dac1c --- /dev/null +++ b/themes/openfreebooks/templates/partials/credits-content.html @@ -0,0 +1,68 @@ +{% set credits = load_data(path="data/credits.json", format="json") %} +{% set libraries = credits.libraries | sort(attribute="name") %} + +
+

{{ credits.intro }}

+

+ {{ credits.contributors_note }} + View contributors. +

+ +
+

This project

+ +
+ +
+

Third party acknowledgements

+

+ {{ credits.project.name }} uses the open source libraries below (in alphabetical order): +

+ {% for lib in libraries %} +
+

+ {{ lib.name }} +

+

Version {{ lib.version }}

+

+ {% if lib.license_url %} + {{ lib.license }} + {% else %} + {{ lib.license }} + {% endif %} +

+

{{ lib.copyright }}

+
+ {% endfor %} +
+ + {% if credits.hosting %} +
+

Hosting & deploy

+ {% for item in credits.hosting %} +
+

+ {{ item.name }} +

+ {% if item.version %} +

Version {{ item.version }}

+ {% endif %} +

{{ item.note }}

+
+ {% endfor %} +
+ {% endif %} +
diff --git a/themes/openfreebooks/templates/partials/icons/social/bluesky.html b/themes/openfreebooks/templates/partials/icons/social/bluesky.html new file mode 100644 index 0000000..942d7dd --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/bluesky.html @@ -0,0 +1,11 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/discord.html b/themes/openfreebooks/templates/partials/icons/social/discord.html new file mode 100644 index 0000000..b0810fa --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/discord.html @@ -0,0 +1,14 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/email.html b/themes/openfreebooks/templates/partials/icons/social/email.html new file mode 100644 index 0000000..664c065 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/email.html @@ -0,0 +1,12 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/facebook.html b/themes/openfreebooks/templates/partials/icons/social/facebook.html new file mode 100644 index 0000000..b523b69 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/facebook.html @@ -0,0 +1,11 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/github.html b/themes/openfreebooks/templates/partials/icons/social/github.html new file mode 100644 index 0000000..77cec19 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/github.html @@ -0,0 +1,11 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/gitlab.html b/themes/openfreebooks/templates/partials/icons/social/gitlab.html new file mode 100644 index 0000000..5c474b2 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/gitlab.html @@ -0,0 +1,11 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/instagram.html b/themes/openfreebooks/templates/partials/icons/social/instagram.html new file mode 100644 index 0000000..8659e8e --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/instagram.html @@ -0,0 +1,13 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/linkedin.html b/themes/openfreebooks/templates/partials/icons/social/linkedin.html new file mode 100644 index 0000000..9309632 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/linkedin.html @@ -0,0 +1,15 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/mastodon.html b/themes/openfreebooks/templates/partials/icons/social/mastodon.html new file mode 100644 index 0000000..768c712 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/mastodon.html @@ -0,0 +1,12 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/medium.html b/themes/openfreebooks/templates/partials/icons/social/medium.html new file mode 100644 index 0000000..52152d6 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/medium.html @@ -0,0 +1,16 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/orcid.html b/themes/openfreebooks/templates/partials/icons/social/orcid.html new file mode 100644 index 0000000..6045d80 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/orcid.html @@ -0,0 +1,11 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/rss.html b/themes/openfreebooks/templates/partials/icons/social/rss.html new file mode 100644 index 0000000..a73a898 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/rss.html @@ -0,0 +1,13 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/scholar.html b/themes/openfreebooks/templates/partials/icons/social/scholar.html new file mode 100644 index 0000000..347fc4f --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/scholar.html @@ -0,0 +1,12 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/substack.html b/themes/openfreebooks/templates/partials/icons/social/substack.html new file mode 100644 index 0000000..37c24f4 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/substack.html @@ -0,0 +1,14 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/threads.html b/themes/openfreebooks/templates/partials/icons/social/threads.html new file mode 100644 index 0000000..184ff1a --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/threads.html @@ -0,0 +1,11 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/tiktok.html b/themes/openfreebooks/templates/partials/icons/social/tiktok.html new file mode 100644 index 0000000..7f2ceb9 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/tiktok.html @@ -0,0 +1,11 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/website.html b/themes/openfreebooks/templates/partials/icons/social/website.html new file mode 100644 index 0000000..d9d32cc --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/website.html @@ -0,0 +1,15 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/x.html b/themes/openfreebooks/templates/partials/icons/social/x.html new file mode 100644 index 0000000..7c066e5 --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/x.html @@ -0,0 +1,12 @@ + diff --git a/themes/openfreebooks/templates/partials/icons/social/youtube.html b/themes/openfreebooks/templates/partials/icons/social/youtube.html new file mode 100644 index 0000000..9ed9dfb --- /dev/null +++ b/themes/openfreebooks/templates/partials/icons/social/youtube.html @@ -0,0 +1,12 @@ + diff --git a/zola.toml b/zola.toml index 897142d..a51fb70 100644 --- a/zola.toml +++ b/zola.toml @@ -21,3 +21,4 @@ site_title = "Open Free Books" github_url = "https://github.com/hananoshikayomaru/openfreebooks" browse_url = "/browse/" about_url = "/about/" +credits_url = "/credits/"