Skip to content

Migrate website to Next.js rebuild (history-preserving)#195

Merged
tillkamppeter merged 102 commits into
masterfrom
redesign-nextjs
Jun 15, 2026
Merged

Migrate website to Next.js rebuild (history-preserving)#195
tillkamppeter merged 102 commits into
masterfrom
redesign-nextjs

Conversation

@rudra-iitm

Copy link
Copy Markdown
Collaborator

Migrate the OpenPrinting website to the Next.js rebuild

This PR replaces the current Jekyll site with the new Next.js + Tailwind + Framer Motion rebuild, while preserving the complete existing Git history. It is opened as a draft for maintainer review — it does not change master or any repo settings on its own.

History preservation (most important)

This is a merge of two previously-unrelated histories, not a force-push:

Parent Lineage Commits
1 master — 7 years of OpenPrinting site history 891
2 redesign — the Next.js rewrite 70
  • The working tree of the merge equals the redesign tree exactly (no leftover Jekyll files).
  • No history was rewritten and no commits were dropped. Every author, timestamp, and commit on both sides remains reachable via git log. Authors such as Michael R Sweet, Till Kamppeter, Zdenek Dohnal, dependabot, etc. are fully preserved on the first-parent history.
  • git log --first-parent continues to show the original master timeline, with this merge on top.

What changed in config for production

  • Base path (config/site.config.ts): defaults to "" (domain root). This is the org root Pages site (https://openprinting.github.io/), so a project-style /openprinting.github.io prefix would 404 every asset/CSS/JS/link. ?? "" keeps an explicit NEXT_PUBLIC_BASE_PATH override possible for sub-path previews.
  • Repo owner set to OpenPrinting so repo slug, links, and Giscus mapping target this repository.
  • Giscus: repoId now points at this repo. This repo has no "Blog Comments" discussion category, so comments currently map to General. ⚠️ A maintainer may prefer to create a dedicated Announcements-type "Blog Comments" category and update categoryId in config/site.config.ts.
  • Workflows: build.yml / deploy.yml now trigger on master (was main).

⚠️ Required at merge time (repo admin only)

GitHub Pages for this repo is currently the legacy Jekyll builder (build_type: legacy, source master/root). This PR's tree is Next.js, not Jekyll. Before/when this lands on master, Pages "Build and deployment → Source" must be switched to "GitHub Actions" (the included deploy.yml builds the static export and publishes it). Otherwise Pages will try to Jekyll-build a Next.js tree and the live site will break. There is no custom domain (cname: null), so no CNAME handling is needed.

Validation performed locally

  • tsc --noEmit typecheck
  • next lint (no warnings/errors)
  • ✅ RSS generation — links are correct root URLs (https://openprinting.github.io/...)
  • ✅ Search index generation — root-relative paths, no double prefix
  • ⏳ Full next build runs the Foomatic prebuild which needs Linux-only system packages — it runs in CI (build.yml) on this PR.

Rollback

Trivial and safe: master is untouched. If anything is wrong, close the PR (and, if already merged, the merge can be reverted; the legacy Pages source can be restored). No history is lost either way.

rudra-iitm and others added 30 commits March 17, 2025 23:26
feat(authors): add reusable AuthorCard component
…es (#8)

feat(authors): add reusable AuthorCard component and fix all linting issues
[feat add]: integrate AuthorCard into news post layout
…#11)

feat(news): migrate all posts from old Jekyll site into Next.js contents

---------

Co-authored-by: Rudra Pratap Singh <rudransh.iitm@gmail.com>
* feat(posts): add automatic redirect support for previous slugs

* fix(posts): decode slug before matching post filenames
…18)

Implemented a complete client-side search system with build-time indexing, markdown AST-based content normalization, and MiniSearch integration. Added a responsive search modal with keyboard shortcuts, debounced input, loading states, and improved UI/UX, along with proper typing, production compatibility, and documentation.
…te (#13)

Fixed React Server Components CVE vulnerabilities by updating dependencies (next, react-server-dom-webpack, react-server-dom-parcel, and react-server-dom-turbopack) to secure versions using the fix-react2shell-next tool, ensuring all package.json files use patched versions based on the official React advisory. Improved site navigation by replacing scroll-based links with route-based navigation and resolving link/button issues. Implemented and migrated multiple website pages including About Us, Contribute, Contact, Downloads, Documentation, Driverless, and other legacy markdown pages. Added a fully functional projects section, news listing with sidebar and year-based navigation, and homepage improvements such as rendering latest posts and aligning hero/info sections with the live site. Fixed theme behavior to follow the system color scheme, updated author card styling for light mode, aligned the footer globally, corrected homepage interactions, and resolved build issues for Next.js 15 static export. Also cleaned content by removing non-legacy news files, syncing posts, updating dependencies, and adjusting the search index.
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: Rudra Pratap Singh rudransh.iitm@gmail.com
style: Refine UI styling and update color palette

Refined the overall UI styling by updating the color palette and adjusting layouts across multiple components and pages to provide a cleaner and more consistent visual refresh.

feat: Redesign search modal with spotlight-style interface

Redesigned the search modal to follow a spotlight-style interface for a more modern search experience. Added an escape-to-close feature and improved the presentation of search results.

feat: Improve search input responsiveness and TOC styling

Improved the responsiveness of the search input for better usability and updated the styling of table of contents headings for improved readability.

feat(navbar): Improve mobile search button usability

Enhanced the styling and spacing of the mobile search button in the navbar to make it easier to access and visually consistent with the rest of the interface.

feat(hero): Add subtle banner image to hero section

Added a subtle background banner image to the hero section and adjusted its height to improve visual balance and overall page appeal.
… handling

Added an environment variable `NEXT_PUBLIC_BASE_PATH` to the Next.js configuration for dynamic image path handling based on the production environment. Updated image sources in the Downloads page and hero section to utilize this variable, ensuring correct image loading in different environments. Removed the hardcoded background image URL in the hero section for improved flexibility. Also updated the generated timestamp in the static search index.
…onment flexibility; update generated timestamp in static index
…sed on environment; update generated timestamp in static index
…th; remove unused CSS comments for cleaner code
…ity and responsiveness; update generated timestamp in static index
@tillkamppeter

Copy link
Copy Markdown
Member

Another little issue:

In the main directory is a file named yarn.lock which is modified every time when yarn install is run, but the file belongs to the GIT repo. For me it looks like that it is machine-generated (by yarn install) and therefore should not be part of the GIT repo (if so, just do git rm yarn.lock).

As it is now, I always have to do git stash between test runs (git pull; yarn install; yarn dev).

If yarn.lock was actually written by you, but each yarn install run modifies it by adding random tokens or checksums to it, then create a yarn.lock.in for the GIT repo and let the build/install process copy it to yarn.lock in the beginning.

A correct GIT repo does not modify any of the files belonging to the repo during the build, test, and install process. The process can add files, but not modify any file which is under version control.

@rudra-iitm

Copy link
Copy Markdown
Collaborator Author

Another little issue:

In the main directory is a file named yarn.lock which is modified every time when yarn install is run, but the file belongs to the GIT repo. For me it looks like that it is machine-generated (by yarn install) and therefore should not be part of the GIT repo (if so, just do git rm yarn.lock).

As it is now, I always have to do git stash between test runs (git pull; yarn install; yarn dev).

If yarn.lock was actually written by you, but each yarn install run modifies it by adding random tokens or checksums to it, then create a yarn.lock.in for the GIT repo and let the build/install process copy it to yarn.lock in the beginning.

A correct GIT repo does not modify any of the files belonging to the repo during the build, test, and install process. The process can add files, but not modify any file which is under version control.

Read this article - https://stackoverflow.com/questions/39990017/should-i-commit-the-yarn-lock-file-and-what-is-it-for

@tillkamppeter

Copy link
Copy Markdown
Member

Some small issues:

  • Why is the file public/search/static-index.json in the repo? For me it looks like a machine-generated search index file, to be regenerated on each site rebuild (by the CI/CD GitHub workflow which happens after each commit).
  • On your announcement blog page you list the contributors, for each one a paragraph starting with the avatar, then the name and then the GitHub link. After that, separated by a long dash you start the text in the same line. and let it flow into the following lines. Due the avatar being larger than the font, the first line is more distant from the others and gets unintentionally highlighted, letting whatever item is in this line, this item being highlighted. Especially with Gaty I see that an item which is not the most important is in that first line. Therefore I suggest to start the description in a new line after the first, just put a newline character instead of the long dash right after the GitHub link. Then the description text stands completely together with uniform line spacing and not highlighting anything without intention.
  • I would call the "Hall of Fame" page "This Website's Hall of Fame", as with just "Hall of Fame" some people could overlook that this is about the website developers and not about the open source printing developers.

@tillkamppeter

Copy link
Copy Markdown
Member

Also do not forget to mention in the README.md:

  • To mention that the Yarn installer is sometimes called yarn, sometimes yarnpkg
  • Installation/Build instructions for Debian/Ubuntu
  • Need of yarn build to include Foomatic database
  • Need to git stash or at least reset yarn.lock (please add command to reset just this file) before further git actions (git pull, git commit, ...).

…out, rename Hall of Fame, expand README

- Git-ignore and untrack public/search/* (regenerated by yarn build)
- Start contributor descriptions on a new line in the website announcement post
- Rename 'Hall of Fame' to 'This Website's Hall of Fame'
- README: yarn/yarnpkg naming, Debian/Ubuntu setup, build-time data generation, yarn.lock reset; remove migration notes
@tillkamppeter

tillkamppeter commented Jun 9, 2026

Copy link
Copy Markdown
Member

Issues:

  • Word breaking at line end: If a long word reaches the line end and does not fit in, it is just broken, not cut at the end of the last fitting syllable and hyphenated, or just no word breaks done. Please check whether in yarn or Node.js you can set hyphenation style/language or suppress breaking words.
  • If I go to the display of a PPD file on the old (current) site (URI generated by clicking button for displaying the PPD for the Alps MD-2010 with the ppmtomd driver)
https://openprinting.org/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010&.submit=Generate+PPD+file&show=1&.cgifields=show&.cgifields=shortgui

and apply the URI to the test copy of the new site via

http://localhost:3000/foomatic/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010&.submit=Generate+PPD+file&show=1&.cgifields=show&.cgifields=shortgui

I get an error:

Server Error

Error: Page "/[...slug]/page" is missing param "/foomatic/ppd-o-matic.php" in "generateStaticParams()", which is required with "output: export" config.

This error happened while generating the page. Any console logs will be displayed in the terminal window.

DevServer.renderToResponseWithComponentsImpl
node_modules/next/src/server/base-server.ts (1982:17)

Old URLs should work on the new site, just ignoring parameters which do not exist on the new site any more.

@tillkamppeter

Copy link
Copy Markdown
Member

Also a straight PPD download which works with the old site

wget -O old.ppd 'http://www.openprinting.org/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010'

does not work with the new site:

$ wget -O new.ppd 'http://localhost:3000/foomatic/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010'
--2026-06-09 12:43:44--  http://localhost:3000/foomatic/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:3000... connected.
HTTP request sent, awaiting response...  ⨯ [Error: Page "/[...slug]/page" is missing param "/foomatic/ppd-o-matic.php" in "generateStaticParams()", which is required with "output: export" config.] {
  page: '/foomatic/ppd-o-matic.php'
}
500 Internal Server Error
2026-06-09 12:43:44 ERROR 500: Internal Server Error.

 GET /foomatic/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010 500 in 121ms
$

@tillkamppeter

Copy link
Copy Markdown
Member

Problem seems to be the .php extension. The old site had ppd-o-matic.php, the new has just ppd-o-matic. So ppd-o-matic.php in the URL needs to get mapped to ppd-o-matic, or generally, all .php needs to be filtered from the URL.

- Introduced QueryApiClient to handle printer queries with support for text and XML formats.
- Updated legacy redirect logic to resolve paths based on parameters.
- Enhanced the generate-query-api script to create static endpoints for printers and drivers.
- Improved CSS styles for better text wrapping and hyphenation in prose elements.
- Added support for manufacturer filtering in the printer list page.
- Updated package.json to include new query API generation script.
- Added new legacy redirects for home and database paths.
@tillkamppeter

Copy link
Copy Markdown
Member

I tried again:

$ wget -O new.ppd 'http://localhost:3000/foomatic/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010'
--2026-06-15 08:51:09--  http://localhost:3000/foomatic/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:3000... connected.
HTTP request sent, awaiting response...  ○ Compiling /foomatic/ppd-o-matic.php ...
 ✓ Compiled /foomatic/ppd-o-matic.php in 20.9s
200 OK
Length: unspecified [text/html]
Saving to: ‘new.ppd’

new.ppd                 [ <=>                ]  57.70K  --.-KB/s    in 0.02s   

2026-06-15 08:51:31 (3.72 MB/s) - ‘new.ppd’ saved [59080]

 GET /foomatic/ppd-o-matic.php?driver=ppmtomd&printer=Alps-MD-2010 200 in 22708ms
$

This time now obvious error got reported, but the whole download process took rather long time, around 30 sec, and the resulting file was garbage.

new.ppd.txt

@tillkamppeter

Copy link
Copy Markdown
Member

Another point is the query API. Please see the examples in the OpenPrinting News November 2021 and September 2022, URLs containing query. These should all work with the new site.

When testing with yarn.dev, replace https://openprinting.org/ with http://localhost:3000/foomatic/ when entering a wget or curl command line or entering the URL in your browser.

Please test all the query and ppd-o-matic scenarios and see whether their output is correct.

@rudra-iitm

rudra-iitm commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

@tillkamppeter Thanks for testing this carefully — both points come down to the same root cause, and I've fixed what's fixable and want to be transparent about one hard constraint.

Why the downloads came back as "garbage"

The site is a fully static export on GitHub Pages — there's no PHP/CGI or any server-side code, and that's a deliberate constraint (free, permanent hosting). A static host looks up a file by path and discards the query string before it serves anything. So query.php?type=printer&make=HP and ppd-o-matic.php?driver=…&printer=… are served the same bytes regardless of the parameters, and the page resolves the query in the browser with JavaScript. That works when you open the URL in a browser, but a client that doesn't run JS — wget, curl, gets the HTML page back instead of the data. That's the file you saw. It's not a bug in the page; it's how static hosting works, and no amount of code on a backend-less host can make a query-string URL vary for a non-JS client.

The machine interface (works with wget/curl/tools today)

Because the path is the only thing a static host can key on, the database query API and the PPDs are exposed as plain files. These are generated at build time and work directly with wget:

https://openprinting.github.io/query/makes.txt
https://openprinting.github.io/query/printers/HP.txt
https://openprinting.github.io/query/drivers/HP-LaserJet_4050.txt
https://openprinting.github.io/ppds/Alps-MD-2010-ppmtomd.ppd

(Append .xml instead of .txt for XML; PPDs are served as application/vnd.cups-ppd.) The driver lists are keyed by printer id (<make>-<model>, spaces → underscores), PPD files are <printer-id>-<driver>.ppd, and there's a full index at /query/index.json. I've documented the complete legacy-URL → static-path mapping in the README.

On the original query.php/ppd-o-matic.php URLs and the News examples

  • They now work correctly in a browser (I fixed a routing bug that was returning HTTP 500 on /foomatic/query.php, and a matching bug where make=HP&model=HP-LaserJet_4050 returned zero results — it now correctly returns the printer and its drivers). All the Nov 2021 and Sep 2022 examples were re-tested.
  • For scripts/tools/wget, the path-based URLs above are the interface.
  • Two original features have no static equivalent because they need request-time computation: fuzzy device-ID matching (printer=MFG:…;MDL:…;) works in the browser only, and papps=true depended on live Printer Application Snaps running on the old server, so it's outside the static database export.

If keeping the literal query.php?… URLs working for wget is important, the only way on a static origin is a proxy/CDN in front that rewrites query strings — but that steps outside free GitHub-only hosting, so I've gone with the path-based interface instead.

@tillkamppeter

Copy link
Copy Markdown
Member

OK, thank you very much.

I have created the query web API many years ago. I do not know about any user of it. At least I never got bug reports or feature requests concerning it. So mot probably it has no users and we can live without it. If there turn up bug reports because of it missing, we direct the people to the Machine Interface you mention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants