diff --git a/content/showcase/HomeByMe.yml b/content/showcase/HomeByMe.yml deleted file mode 100644 index bfbbcc54..00000000 --- a/content/showcase/HomeByMe.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: HomeByME -description: A home design application, compiled to the web with Cheerp. -url: https://home.by.me/en/ -heroImage: ./homebyme.png -tags: - - Cheerp diff --git a/content/showcase/boardspace.png b/content/showcase/boardspace.png deleted file mode 100644 index c0ade324..00000000 Binary files a/content/showcase/boardspace.png and /dev/null differ diff --git a/content/showcase/boardspace.yml b/content/showcase/boardspace.yml deleted file mode 100644 index 64aecb52..00000000 --- a/content/showcase/boardspace.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: Boardspace -description: A board game playing application using AWT. Over 100 games are available to play against human and robot opponents using WebSockets. -url: https://boardspace.net/login.html -heroImage: ./boardspace.png -tags: - - CheerpJ diff --git a/content/showcase/bp_env.md b/content/showcase/bp_env.md new file mode 100644 index 00000000..1626de4d --- /dev/null +++ b/content/showcase/bp_env.md @@ -0,0 +1,20 @@ +--- +title: Full-Stack Development Environment +description: A full Vite + Svelte full-stack development environment, running fully in-browser, with public URLs. +demo_url: https://vitedemo.browserpod.io/ +repository_url: https://github.com/leaningtech/labs/blob/main/sites/labs/src/components/BrowserPodDemo_Beta.svelte +author: Leaning Technologies +project_type: Company Demo +niche: Dev utilities +tags: + - BrowserPod +hero_image: "./bp_env.png" +--- + +The main strength of Browserpod is its capability to run a project directly in the user’s browser, without any explicit setup or installation, and secured by the browser’s sandbox. + +The current demo showcases one of the above capabilities, where BrawserPod is being used to build a full Vite + Svelte full-stack development environment, running entirely in the browser, with public URLs. + +Any port that is bound to public interfaces inside the pod is exposed to the internet via a secret link. By sharing a link like this, you can show early adopters or clients how your application works without setting up any actual hosting. Moreover, you’ll be able to test your application from mobile devices, for example, by encoding the link in a QR code on your main device screen. + +Learn more about Browserpod on the [documentation site](https://browserpod.io/docs/overview). diff --git a/content/showcase/bp_env.png b/content/showcase/bp_env.png new file mode 100644 index 00000000..7fc58c84 Binary files /dev/null and b/content/showcase/bp_env.png differ diff --git a/content/showcase/browsercraft.md b/content/showcase/browsercraft.md new file mode 100644 index 00000000..d68fb3d0 --- /dev/null +++ b/content/showcase/browsercraft.md @@ -0,0 +1,24 @@ +--- +title: Browsercraft +description: Minecraft running unmodified in the browser! +demo_url: https://browsercraft.cheerpj.com/ +repository_url: https://github.com/leaningtech/browsercraft +author: Leaning Technologies +project_type: Company Demo +niche: Videogames +tags: + - CheerpJ +hero_image: "./browsercraft.png" +--- + +## What is it? + +Browsercraft runs unmodified Minecraft (version 1.2.5) in the browser using CheerpJ, a Java runtime for modern browsers. The experience is intentionally limited to 3 minutes; please refer to [minecraft.net](minecraft.net) for the full game. + +## What this is not + +It is not a replacement for the official Minecraft, nor a reimplementation in another programming language. This is also not a modified version of the game: we do not alter the code in any way, we simply run the original JARs. + +## How it works + +CheerpJ is a Java Virtual Machine written in WebAssembly that runs entirely in your browser. It can execute any Java application without modification and without requiring the source code. This demo showcases these capabilities by running an older version (1.2.5) of Minecraft and LWJGL entirely within the browser. diff --git a/content/showcase/browsercraft.yml b/content/showcase/browsercraft.yml deleted file mode 100644 index 8d85d3d2..00000000 --- a/content/showcase/browsercraft.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: Browsercraft -description: Minecraft running unmodified in the browser! -url: https://browsercraft.cheerpj.com/ -heroImage: ./browsercraft.png -tags: - - CheerpJ diff --git a/content/showcase/cheerpj.md b/content/showcase/cheerpj.md new file mode 100644 index 00000000..6635e624 --- /dev/null +++ b/content/showcase/cheerpj.md @@ -0,0 +1,26 @@ +--- +title: CheerpJ +description: The WebAssembly-based Java Virtual Machine for the browser. +demo_url: https://cheerpj.com/ +repository_url: https://github.com/leaningtech/cheerpj-meta +author: Leaning Technologies +project_type: Company Product +niche: Compilers +tags: + - Cheerp +hero_image: "./cheerpj.png" +--- + +## What is CheerpJ? + +CheerpJ is a WebAssembly-based Java Virtual Machine for the browser. This means Java applications can be executed from the browser with no Java installation. It has extensive compatibility with Java 8, 11, and 17, providing a full runtime environment for running Java applications, applets, libraries, and Java Web Start / JNLP applications in the browser without plugins. + +## How it works + +The magic behind CheerpJ is Cheerp, which was used for compiling full Java SE 8, 11, and 17 runtimes based on OpenJDK. This runtime was originally written in C++ and compiled to WebAssembly and JavaScript, making it 100% browser compatible. The architecture is designed to support multiple versions of Java, as well as custom runtimes. + +## What can CheerpJ run? + +CheerpJ Core can run standalone Java applications, applets, JNLPs, and also in library mode. We have published two end-user-ready browser extensions based on CheerpJ technology: the CheerpJ Applet Runner and the CheerpJ JNLP Runner. + +You can learn more about how to use CheerpJ in our [documentation](https://cheerpj.com/docs). diff --git a/content/showcase/cheerpj.png b/content/showcase/cheerpj.png new file mode 100644 index 00000000..23ba3904 Binary files /dev/null and b/content/showcase/cheerpj.png differ diff --git a/content/showcase/cheerpj.webp b/content/showcase/cheerpj.webp new file mode 100644 index 00000000..e1cebd62 Binary files /dev/null and b/content/showcase/cheerpj.webp differ diff --git a/content/showcase/cheerpx.md b/content/showcase/cheerpx.md new file mode 100644 index 00000000..d9eab2bd --- /dev/null +++ b/content/showcase/cheerpx.md @@ -0,0 +1,26 @@ +--- +title: CheerpX +description: The x86 virtualization technology for running executables and operating systems entirely client-side. +demo_url: https://cheerpx.io/ +repository_url: https://github.com/leaningtech/cheerpx-meta +author: Leaning Technologies +project_type: Company Product +niche: Virtual Machines +tags: + - Cheerp +hero_image: "./cheerpx.png" +--- + +## What is CheerpX? + +CheerpX is a powerful x86 virtualization library designed to run unmodified binary applications and libraries in the browser. It leverages a WebAssembly-based sandbox and standard browser APIs to ensure security, even when executing untrusted code. CheerpX supports Linux-compatible system calls and can run many common applications, including complete Linux distributions. + +## How it works + +At its core, CheerpX is a two-tier emulator for the x86 architecture implemented in C++ that has been compiled to JavaScript and WebAssembly using Cheerp. CheerpX features an advanced Just-In-Time compiler that dynamically translates x86 code to WebAssembly as needed. This engine is highly robust, capable of handling dynamically generated and self-modifying code. + +## What is it used for? + +CheerpX is the core technology behind WebVM, one of our most successful public demos with 16k stars on GitHub, as well as Alpine WebVM and the Games Runner browser extension. + +You can learn more about CheerpX on our [documentation site](https://cheerpx.io/docs/overview). diff --git a/content/showcase/cheerpx.png b/content/showcase/cheerpx.png new file mode 100644 index 00000000..f46a970e Binary files /dev/null and b/content/showcase/cheerpx.png differ diff --git a/content/showcase/cjdom.png b/content/showcase/cjdom.png deleted file mode 100644 index b2c8d4dc..00000000 Binary files a/content/showcase/cjdom.png and /dev/null differ diff --git a/content/showcase/cjdom.yml b/content/showcase/cjdom.yml deleted file mode 100644 index adb1944e..00000000 --- a/content/showcase/cjdom.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: CJDom -description: A library providing bindings to common Web/DOM APIs for CheerpJ. -url: https://github.com/reportmill/CJDom -heroImage: ./cjdom.png -tags: - - CheerpJ diff --git a/content/showcase/client-side-code-editor.md b/content/showcase/client-side-code-editor.md new file mode 100644 index 00000000..1ea1596f --- /dev/null +++ b/content/showcase/client-side-code-editor.md @@ -0,0 +1,19 @@ +--- +title: Client-Side Code Editor +description: Practice Python coding client-side in your browser! +repository_url: https://github.com/rheap404/cheerpx_hack +author: Rhea and Rida +project_type: Hackathon Winner 2024 +niche: Dev Utilities +tags: + - CheerpX +hero_image: "./client-side-code-editor.png" +--- + +## What is it? + +This platform allows users to practice coding problems in Python, featuring a split-view workspace with problem instructions on one side and a code editor with a built-in console on the other. The platform runs code client-side using CheerpX, which emulates a virtual machine in the browser — eliminating the need for server-based execution and improving speed, privacy, and scalability. + +## Background + +This project was developed as part of the WebVM Hackathon, leveraging CheerpX for WebAssembly-powered client-side execution of Python code in the browser. It mimics platforms like NeetCode.io, enabling users to practice coding problems and receive immediate feedback by running their code directly in the browser. The goal is to showcase the potential of WebVM for delivering powerful terminal-based applications without the need for native installations. diff --git a/content/showcase/client-side-code-editor.png b/content/showcase/client-side-code-editor.png new file mode 100644 index 00000000..a496743b Binary files /dev/null and b/content/showcase/client-side-code-editor.png differ diff --git a/content/showcase/dragon-court-revived.md b/content/showcase/dragon-court-revived.md new file mode 100644 index 00000000..67aaaf99 --- /dev/null +++ b/content/showcase/dragon-court-revived.md @@ -0,0 +1,25 @@ +--- +title: "Dragon Court: Revived" +description: An old-school fantasy RPG, revived with in-game trading, multiplayer clans, and competitive leaderboards. +demo_url: https://dragoncourt.penguinchilling.com/ +author: Penguin Chilling +project_type: Community +niche: Videogames +tags: + - CheerpJ +hero_image: "./dragon-court-revived.png" +--- + +## What is Dragon Court: Revived? + +Dragon Court was originally a game released around 1997 as a Java Applet, but it became abandonware around 2017. It was created by Fred Haslam, who handled the primary coding and design, with code contributions from Elden Bishop, additional design help from Lawrence Wegner and Diane M. Jones, and artwork by Ted Galaday. + +## The challenge of revival + +The game relies on a dedicated server to handle saving player progress, mailing items between players, building clans, and maintaining leaderboard rankings. Since the original site went down, the Internet Archive's Wayback Machine was used to salvage as much as possible to bring back Dragon Court. + +Only the last known client version was found as a Java Applet. Unfortunately, Java Applets were phased out by modern browsers since 2013 and removed from support by 2015–2017. + +## How CheerpJ made it possible + +Thanks to CheerpJ, the original Dragon Court binary became runnable as WebAssembly and JavaScript in modern browsers without additional setup or tinkering. The final step was restoring the server-side functionality — saving hero progress, trading, clans, and leaderboards — completing the revival of Dragon Court for a new generation of players. diff --git a/content/showcase/dragoncourtrevived.png b/content/showcase/dragon-court-revived.png similarity index 100% rename from content/showcase/dragoncourtrevived.png rename to content/showcase/dragon-court-revived.png diff --git a/content/showcase/dragoncourtrevived.yml b/content/showcase/dragoncourtrevived.yml deleted file mode 100644 index 594dea8e..00000000 --- a/content/showcase/dragoncourtrevived.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: "Dragon Court: Revived" -description: An old-school fantasy RPG, revived with in-game trading, multiplayer clans, and competitive leaderboards. -url: https://dragoncourt.penguinchilling.com/ -heroImage: ./dragoncourtrevived.png -tags: - - CheerpJ diff --git a/content/showcase/flatlaf.md b/content/showcase/flatlaf.md new file mode 100644 index 00000000..08d06695 --- /dev/null +++ b/content/showcase/flatlaf.md @@ -0,0 +1,26 @@ +--- +title: FlatLaf +description: A modern Java Swing look-and-feel showcased running entirely in the browser via CheerpJ. +demo_url: https://flatlaf-demo.labs-leaningtech-com.pages.dev/FlatLaf-Demo/ +repository_url: https://github.com/leaningtech/labs/tree/FlatLaf-Demo +author: Leaning Technologies +project_type: Company Demo +niche: Graphics +tags: + - CheerpJ +hero_image: "./flatlaf.png" +--- + +## What is FlatLaf? + +FlatLaf is a modern open-source look-and-feel framework for Java Swing, providing a clean and contemporary UI. It is widely used as a drop-in replacement for legacy desktop styling. This demo showcases FlatLaf running entirely in the browser using CheerpJ. + +## What the demo includes + +The FlatLaf distribution includes multiple standalone applications. This demo combines two of them into a single browser-based experience: the FlatLaf Demo, which presents a broad overview of Swing components and visual styles, and the FlatLaf Theme Editor, which allows users to create and customize themes interactively. + +Users can design or modify a theme in the Theme Editor and immediately load it into the FlatLaf Demo to preview the result. + +## Technical details + +The demo runs on the CheerpJ Java 17 runtime and executes the original, unmodified FlatLaf JARs. diff --git a/content/showcase/flatlaf.png b/content/showcase/flatlaf.png new file mode 100644 index 00000000..f486bf17 Binary files /dev/null and b/content/showcase/flatlaf.png differ diff --git a/content/showcase/homebyme.md b/content/showcase/homebyme.md new file mode 100644 index 00000000..49190bf3 --- /dev/null +++ b/content/showcase/homebyme.md @@ -0,0 +1,25 @@ +--- +title: HomeByMe +description: A home design application, compiled to the web with Cheerp. +demo_url: https://home.by.me/en/ +author: HomeByMe, Leaning Technologies +project_type: Enterprise Demo +niche: Interior Design +tags: + - Cheerp +hero_image: "./homebyme.png" +--- + +## What is HomeByMe? + +HomeByMe is an online 3D space planning service developed by Dassault Systèmes SE, and powered by Cheerp. + +HomeByMe allows users to design, visualise, and review home and furniture layouts, using intuitive 3D views to allow consumers to easily create detailed floor plans, test various furniture, play with thousands of decoration elements, and experience a virtual immersion into their home. HomeByMe is enjoyed by users worldwide, who have shared over 1.5 million floor plans and interior design ideas with home builders, kitchen retailers, architects, friends, and family. + +## Background + +HomeByMe is primarily written in C++, and its large multi-target codebase was developed over a decade by a team of developers and offered until 2015 as a set of native applications for Desktop and Mobile. With an interest in exploring modern HTML5 web technologies to deliver a browser-based version of their application, and after research and consideration of alternative options, 3DVIA engaged with Leaning Technologies to explore the viability of compiling their multi-target C++ codebase to JavaScript (and later WebAssembly). + +## How Cheerp powers HomeByMe + +Cheerp was introduced in the HomeByMe toolchain in 2015, when Dassault Systèmes started collaborating with Leaning Technologies in the porting of HomeByMe. In the course of a few months of work, their very large application was fully converted and functional in HTML5/JavaScript, and we could put our combined attention to performance and size optimisations. Since then, Cheerp has been used in production to convert all the logic of the application, which has been kept fully in C++, with a new frontend integration written in HTML5/JavaScript. diff --git a/content/showcase/imagej-js.md b/content/showcase/imagej-js.md new file mode 100644 index 00000000..d6a5d7b8 --- /dev/null +++ b/content/showcase/imagej-js.md @@ -0,0 +1,26 @@ +--- +title: ImageJ.js +description: A web port of ImageJ, an open-source image processing tool popular in the scientific community. +demo_url: https://aicell-lab.github.io/imagej.js/ +repository_url: https://github.com/aicell-lab/imagej.js +author: AICell Lab +project_type: Community +niche: Scientific Software +tags: + - CheerpJ +hero_image: "./imagej-js.png" +--- + +## What is ImageJ.js? + +ImageJ is a well-known Java-based software for image analysis, widely used in the scientific community. ImageJ.js brings the full power of ImageJ to the web, enabling professional image analysis on any device with a modern browser. + +## Powered by CheerpJ 3 + +ImageJ.js was enhanced and updated with CheerpJ 3 — a WebAssembly compiler that runs Java applications directly in the browser without any preprocessing. This unlocked capabilities that were impossible in previous versions, such as lifting the image file size limit and enabling proper file system access. + +## Adoption + +Originally created during a hackathon in Dresden and evolved through the ImJoy project, ImageJ.js now serves 1,000–1,500 unique users daily for scientific image analysis, education, and research. + +Learn more about this project [here](https://aicell.io/post/improving-imagej.js/). diff --git a/content/showcase/imagej-js.png b/content/showcase/imagej-js.png new file mode 100644 index 00000000..688f0fda Binary files /dev/null and b/content/showcase/imagej-js.png differ diff --git a/content/showcase/imagej.webp b/content/showcase/imagej.webp deleted file mode 100644 index 0ae6483c..00000000 Binary files a/content/showcase/imagej.webp and /dev/null differ diff --git a/content/showcase/imagej.yml b/content/showcase/imagej.yml deleted file mode 100644 index ec32c857..00000000 --- a/content/showcase/imagej.yml +++ /dev/null @@ -1,7 +0,0 @@ -title: ImageJ.js -description: A web port of ImageJ, an open-source image processing tool popular in the scientific community. -url: https://aicell.io/post/improving-imagej.js/ -# https://github.com/aicell-lab/imagej.js -heroImage: ./imagej.webp -tags: - - CheerpJ diff --git a/content/showcase/itext.png b/content/showcase/itext.png deleted file mode 100644 index 17ed67bb..00000000 Binary files a/content/showcase/itext.png and /dev/null differ diff --git a/content/showcase/itext.yml b/content/showcase/itext.yml deleted file mode 100644 index 0f92361a..00000000 --- a/content/showcase/itext.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: iText -description: Edit PDFs fully client side using the industry standard iText library converted to JavaScript. -url: https://cheerpjdemos.leaningtech.com/iTextDemo.html -heroImage: ./itext.png -tags: - - CheerpJ diff --git a/content/showcase/javafiddle.md b/content/showcase/javafiddle.md new file mode 100644 index 00000000..dbc6a131 --- /dev/null +++ b/content/showcase/javafiddle.md @@ -0,0 +1,24 @@ +--- +title: Java Fiddle +description: Compile, edit, and run Java directly in the browser. +demo_url: https://javafiddle.leaningtech.com/ +repository_url: https://github.com/leaningtech/javafiddle +author: Leaning Technologies +project_type: Company Demo +niche: Dev Utilities +tags: + - CheerpJ +hero_image: "./javafiddle.png" +--- + +## What is Java Fiddle? + +JavaFiddle is an online tool to build and share snippets of Java code, powered by CheerpJ. It was built to showcase the possibilities of client-side browser IDEs and to serve as inspiration for other developers. + +## Features + +Java Fiddle is also used by the community as a free educational tool for the Java programming language, removing the need to install Java locally. JavaFiddle supports Java 8 SE, including Swing. + +## Open source + +This tool is completely open source — feel free to explore how it was built, make suggestions, or contribute! diff --git a/content/showcase/javafiddle.yml b/content/showcase/javafiddle.yml deleted file mode 100644 index cd17c28d..00000000 --- a/content/showcase/javafiddle.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: Java Fiddle -description: Compile, edit and run Java, directly in the browser. -url: https://javafiddle.leaningtech.com/ -heroImage: ./javafiddle.png -tags: - - CheerpJ diff --git a/content/showcase/linux-dungeon.md b/content/showcase/linux-dungeon.md new file mode 100644 index 00000000..571c167c --- /dev/null +++ b/content/showcase/linux-dungeon.md @@ -0,0 +1,20 @@ +--- +title: Linux Dungeon +description: A browser-based fantasy puzzle game that runs entirely in a virtual Linux terminal. +demo_url: https://jfoxuk.github.io/webvm/ +repository_url: https://github.com/JFoxUK/webvm +author: Jonathan Fox, Ruby Tipper +project_type: Hackathon Winner 2025 +niche: Virtual Machines and Education +tags: + - CheerpX +hero_image: "./linux-dungeon.png" +--- + +## What is Linux Dungeon? + +Linux Dungeon is a browser-based fantasy puzzle game that runs entirely in a virtual Linux terminal. Players take on the role of an adventurer trapped in a digital dungeon, where the only way forward is to master real Linux commands. Each room is sealed inside a password-protected `.zip` file, and players must explore directories, decode clues, and edit configs to advance. + +## How it was built + +This project was built for WebVM: Hackathon II, which challenged developers to create educational Linux experiences using CheerpX. By running a full Linux environment client-side in the browser, Linux Dungeon turns command-line learning into an engaging, gamified adventure — no installation required. diff --git a/content/showcase/linux-dungeon.png b/content/showcase/linux-dungeon.png new file mode 100644 index 00000000..a3b48bc2 Binary files /dev/null and b/content/showcase/linux-dungeon.png differ diff --git a/content/showcase/logisim.md b/content/showcase/logisim.md new file mode 100644 index 00000000..b4726447 --- /dev/null +++ b/content/showcase/logisim.md @@ -0,0 +1,20 @@ +--- +title: Logisim.app +description: A complete, browser-based port of the classic Logisim logic circuit simulator. +demo_url: https://logisim.app/ +repository_url: https://github.com/De-Rossi-Consulting/logisim.app +author: Ethan Hale, Martin Nyaga +project_type: Community +niche: Scientific +tags: + - CheerpJ +hero_image: "./logisim.png" +--- + +## What is Logisim.app? + +Explore how modern computers work by building them from the ground up. Logisim.app lets you design logic circuits — from simple adders and multiplexers to full ALUs and CPUs — in exactly the same way as the classic Logisim by Carl Burch. Requiring no downloads or setup, it is fully compatible with existing Logisim circuits and instantly available on the web. + +## How it works + +Logisim.app is a 1:1 port that works by running Java on a WebAssembly JVM via CheerpJ. The Java codebase is the same as the original, with a few targeted modifications to allow Logisim to work within the browser's secure sandbox — including letting users open and save files to disk. diff --git a/content/showcase/logisim.png b/content/showcase/logisim.png new file mode 100644 index 00000000..7142fc20 Binary files /dev/null and b/content/showcase/logisim.png differ diff --git a/content/showcase/nasa-aeronautics.md b/content/showcase/nasa-aeronautics.md new file mode 100644 index 00000000..ec40933a --- /dev/null +++ b/content/showcase/nasa-aeronautics.md @@ -0,0 +1,20 @@ +--- +title: NASA Aeronautics Simulators +description: Interactive simulator applets for aeronautics students, powered by CheerpJ. +demo_url: https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/bga-simulations/ +repository_url: https://github.com/nasa/BGA +author: NASA +project_type: Community +niche: Education +tags: + - CheerpJ +hero_image: "./nasa-aeronautics.png" +--- + +## What is it? + +NASA has multiple educational and interactive applications that serve as a guide for those interested in getting started with aeronautics. In particular, NASA is making use of CheerpJ to run one of their most popular applet collections: the Aeronautics Simulators. CheerpJ has made it possible to run these applets in the modern browser, saving these valuable educational resources from being lost. + +## Try it yourself + +If you are interested in how CheerpJ can help your applets run again in the browser, please take a look at our [applet tutorial](https://cheerpj.com/docs/getting-started/Java-applet). diff --git a/content/showcase/nasa-applets.png b/content/showcase/nasa-aeronautics.png similarity index 100% rename from content/showcase/nasa-applets.png rename to content/showcase/nasa-aeronautics.png diff --git a/content/showcase/nasa-applets.yml b/content/showcase/nasa-applets.yml deleted file mode 100644 index 6fb1f9b2..00000000 --- a/content/showcase/nasa-applets.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: NASA Aeronautics Simulators -description: Interactive simulator applets for aeoronautics students, powered by CheerpJ. -url: https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/drop-simulator/ -heroImage: ./nasa-applets.png -tags: - - CheerpJ diff --git a/content/showcase/openastex.png b/content/showcase/openastex.png deleted file mode 100644 index 14e9d2cd..00000000 Binary files a/content/showcase/openastex.png and /dev/null differ diff --git a/content/showcase/openastex.yml b/content/showcase/openastex.yml deleted file mode 100644 index 3f774089..00000000 --- a/content/showcase/openastex.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: OpenAstexViewer -description: A complex Java applet with 3D rendering running in any browser using CheerpJ. -url: https://cheerpjdemos.leaningtech.com/OpenAstexViewer.html -heroImage: ./openastex.png -tags: - - CheerpJ diff --git a/content/showcase/phet.md b/content/showcase/phet.md new file mode 100644 index 00000000..225e9dcf --- /dev/null +++ b/content/showcase/phet.md @@ -0,0 +1,22 @@ +--- +title: PhET Interactive Simulations +description: Interactive physics simulations from the University of Colorado Boulder, powered by CheerpJ. +demo_url: https://phet.colorado.edu/en/simulations/filter?type=cheerpj +repository_url: https://github.com/phetsims +author: University of Colorado Boulder +project_type: Community +niche: Education +tags: + - CheerpJ +hero_image: "./phet.png" +--- + +## What is PhET? + +Founded in 2002 by Nobel Laureate Carl Wieman, the PhET Interactive Simulations project at the University of Colorado Boulder creates free interactive math and science simulations. PhET sims are based on extensive education research and engage students through an intuitive, game-like environment where they learn through exploration and discovery. + +## What it offers + +Their platform offers resources for teachers and students across a wide range of subjects. PhET provides an extensive collection of applications covering statistics, chemistry, physics, and more, each delivering an interactive learning experience. + +Several of these applications are implemented as Java applets — a technology no longer compatible with modern browsers. CheerpJ makes it possible to run them again, preserving these educational resources for students and educators worldwide. diff --git a/content/showcase/phet.yml b/content/showcase/phet.yml deleted file mode 100644 index a434ada3..00000000 --- a/content/showcase/phet.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: PHET Interactive Simulations -description: Interactive physics simulations from the University of Colorado Boulder, powered by CheerpJ. -url: https://phet.colorado.edu/en/simulations/filter?type=cheerpj -heroImage: ./phet.png -tags: - - CheerpJ diff --git a/content/showcase/snapcode.md b/content/showcase/snapcode.md new file mode 100644 index 00000000..0250584d --- /dev/null +++ b/content/showcase/snapcode.md @@ -0,0 +1,20 @@ +--- +title: SnapCode +description: A full-featured Java IDE that runs in the browser. +demo_url: https://reportmill.com/SnapCode/ +repository_url: https://github.com/reportmill/SnapCode +author: ReportMill Software +project_type: Community +niche: Developer Tools +tags: + - CheerpJ +hero_image: "./snapcode.png" +--- + +## What is SnapCode? + +SnapCode is a full-featured Java IDE that runs in the browser. It is free, modern, powerful, and tailored for education — making it the fastest and easiest way to start writing and sharing Java code. + +## Features + +SnapCode offers modern coding features, support for Java REPL (Read-Eval-Print-Loop), support for working with projects in the cloud, and full-featured library support for UI, graphics, charting, 3D, and more. diff --git a/content/showcase/snapcode.png b/content/showcase/snapcode.png new file mode 100644 index 00000000..0d1bb6cd Binary files /dev/null and b/content/showcase/snapcode.png differ diff --git a/content/showcase/swingset3.md b/content/showcase/swingset3.md new file mode 100644 index 00000000..232120e7 --- /dev/null +++ b/content/showcase/swingset3.md @@ -0,0 +1,20 @@ +--- +title: SwingSet3 +description: Java Swing components running in the browser with CheerpJ. +demo_url: https://cheerpj-example-swingset3.leaningtech.com/ +repository_url: https://github.com/leaningtech/cheerpj-example-swingset3/blob/main/index.html +author: Leaning Technologies +project_type: Company Demo +niche: Software Utilities +tags: + - CheerpJ +hero_image: "./swingset3.png" +--- + +## What is SwingSet3? + +SwingSet3 is an open source demo of Java components from the Swing Graphical User Interface (GUI) Toolkit. It was originally created by Oracle/Sun Microsystems and is currently being developed as a public java.net project by SwingLabs. + +## What this demo showcases + +We have taken the SwingSet3 Java Demo as a benchmark to showcase how a graphical standalone Java application with Swing components can run fully in the browser, client-side. You can find a full tutorial on how to recreate this CheerpJ demo [here](https://cheerpj.com/docs/tutorials/swingset3). diff --git a/content/showcase/swingset3.yml b/content/showcase/swingset3.yml deleted file mode 100644 index 2116b3dc..00000000 --- a/content/showcase/swingset3.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: SwingSet3 -description: Java Swing components to HTML5 with CheerpJ -url: https://cheerpj-example-swingset3.leaningtech.com/ -heroImage: ./swingset3.png -tags: - - CheerpJ diff --git a/content/showcase/teeworlds.md b/content/showcase/teeworlds.md new file mode 100644 index 00000000..e99a055e --- /dev/null +++ b/content/showcase/teeworlds.md @@ -0,0 +1,28 @@ +--- +title: TeeWorlds +description: Retro, multiplayer 2D shooting game running in the browser using Cheerp, WebRTC, and Firebase. +demo_url: https://teeworlds.leaningtech.com +repository_url: https://github.com/leaningtech/cheerpnet +author: Leaning Technologies +project_type: Company Demo +niche: Videogames +tags: + - Cheerp +hero_image: "./teeworlds.png" +--- + +## What is it? + +Our team has ported the classic C++ multiplayer game Teeworlds to run entirely in a web browser, using Cheerp, WebRTC, and Firebase as the core technologies. The aim was to move both the client and server components of the game into the browser with minimal changes to the original codebase using modern web technologies. + +## The networking challenge + +A key challenge was networking. Standard web approaches like HTTP or WebSockets rely on TCP, which introduces latency and ordering guarantees that are poorly suited for fast-paced games. To solve this, our team used WebRTC, which supports both reliable and unreliable data channels and can approximate UDP-style communication in the browser. WebRTC enables peer-to-peer connections and works across NATs using ICE, STUN, and TURN, but it requires a separate signalling mechanism to establish connections between peers. + +## How it works + +Cheerp, a C++ compiler that targets WebAssembly and JavaScript, was used to compile both the game client and server logic to run inside the browser. To avoid rewriting large portions of the game, the authors implemented a socket-like abstraction that mimics UDP networking while internally using WebRTC data channels. Instead of IP addresses, peers are identified using unique keys, and WebRTC connections are created lazily only when data is first sent. + +For signalling, matchmaking, and server discovery, Firebase was used. Firebase stores the list of available game sessions and handles the exchange of WebRTC connection metadata between peers. This architecture allows one player's browser to act as the game server, resulting in a fully serverless multiplayer game that can be deployed as static web content. The project shows that complex C++ multiplayer games can be brought to the web with minimal refactoring while retaining real-time performance. + +You can read more details about this demo [here](https://medium.com/leaningtech/porting-a-c-multiplayer-game-to-the-web-with-cheerp-webrtc-and-firebase-29fbbc62c5ca). diff --git a/content/showcase/teeworlds.png b/content/showcase/teeworlds.png new file mode 100644 index 00000000..2ac8e626 Binary files /dev/null and b/content/showcase/teeworlds.png differ diff --git a/content/showcase/webvm-alpine.md b/content/showcase/webvm-alpine.md new file mode 100644 index 00000000..b3aa9e3e --- /dev/null +++ b/content/showcase/webvm-alpine.md @@ -0,0 +1,20 @@ +--- +title: WebVM Alpine +description: Graphical Linux Alpine running client-side in your browser. +demo_url: https://webvm.io/alpine.html +repository_url: https://github.com/leaningtech/webvm +author: Leaning Technologies +project_type: Company Demo +niche: Virtual Machines +tags: + - CheerpX +hero_image: "./webvm-alpine.png" +--- + +## What is WebVM Alpine? + +WebVM 2.0 brought major improvements to graphical application support, including the ability to boot a complete Alpine desktop environment entirely in the browser. This demo showcases that capability, running a full Linux desktop client-side without any installation. + +## Design choices + +We have settled on using i3, a minimalistic window manager, to ensure the demo is enjoyable by most users — including on mobile devices — without consuming excessive amounts of data. Future improvements in our roadmap will make it practical to run heavier environments like XFCE in upcoming releases. diff --git a/content/showcase/webvm-alpine.png b/content/showcase/webvm-alpine.png new file mode 100644 index 00000000..618eb281 Binary files /dev/null and b/content/showcase/webvm-alpine.png differ diff --git a/content/showcase/webvm.md b/content/showcase/webvm.md new file mode 100644 index 00000000..4b6caaf7 --- /dev/null +++ b/content/showcase/webvm.md @@ -0,0 +1,24 @@ +--- +title: WebVM +description: Linux running client-side within your browser tab. +demo_url: https://webvm.io/ +repository_url: https://github.com/leaningtech/webvm +author: Leaning Technologies +project_type: Company Demo +niche: Virtual Machines +tags: + - CheerpX +hero_image: "./webvm.png" +--- + +## What is WebVM? + +WebVM is a virtual Linux environment running in the browser via WebAssembly. It is powered by the CheerpX virtualization engine, which enables safe, sandboxed, client-side execution of x86 binaries. Being built entirely on standard web technologies — WebAssembly in particular — it is fully isolated from your system and your other browser tabs. + +## How it works + +CheerpX includes an x86-to-WebAssembly JIT compiler, a virtual block-based file system, and a Linux syscall emulator. Together, these components make it possible to run unmodified Linux software directly inside a browser tab. + +## Claude Integration + +WebVM integrates the Computer Use feature from Claude. Since Claude APIs can be used directly from a browser tab, it is possible to combine them with WebVM to create a secure and private environment to experiment with Claude Computer Use capabilities. Read more about the WebVM and Claude integration in our dedicated [blog post](https://cheerpx.io/blog/webvm-claude). diff --git a/content/showcase/webvm.yml b/content/showcase/webvm.yml deleted file mode 100644 index 8da1a3e6..00000000 --- a/content/showcase/webvm.yml +++ /dev/null @@ -1,6 +0,0 @@ -title: WebVM -description: Linux running client-side within your browser tab -url: https://webvm.io/ -heroImage: ./webvm.png -tags: - - CheerpX diff --git a/packages/astro-theme/components/BlogPostCard.astro b/packages/astro-theme/components/BlogPostCard.astro index 88906992..f72e5b1f 100644 --- a/packages/astro-theme/components/BlogPostCard.astro +++ b/packages/astro-theme/components/BlogPostCard.astro @@ -1,8 +1,8 @@ --- import { getEntry, type CollectionEntry } from "astro:content"; +import { Image } from "astro:assets"; import FormattedDate from "./FormattedDate.astro"; import { resolveAuthors } from "../lib/blog"; -import { Image } from "astro:assets"; import { productFromUrl } from "../lib/products"; const product = productFromUrl(Astro.url); @@ -14,6 +14,11 @@ interface Props { } const { post: postOrSlug, showMetadata = false, size = "narrow" } = Astro.props; + +if (!postOrSlug) { + return null; +} + const post = typeof postOrSlug === "string" ? await getEntry("blog", postOrSlug) diff --git a/packages/astro-theme/components/DemoCard.astro b/packages/astro-theme/components/DemoCard.astro new file mode 100644 index 00000000..66524ebd --- /dev/null +++ b/packages/astro-theme/components/DemoCard.astro @@ -0,0 +1,81 @@ +--- +import { getEntry, type CollectionEntry } from "astro:content"; +import { Image } from "astro:assets"; +import { productFromUrl } from "../lib/products"; + +const product = productFromUrl(Astro.url); + +interface Props { + demo: CollectionEntry<"showcase"> | CollectionEntry<"showcase">["slug"]; + showMetadata?: boolean; + size?: "wide" | "narrow"; +} + +const { demo: demoOrSlug, showMetadata = false, size = "narrow" } = Astro.props; + +const demo = + typeof demoOrSlug === "string" + ? await getEntry("showcase", demoOrSlug) + : demoOrSlug; + +//choose hover link color based on product +const productName = typeof product === "undefined" ? "Labs" : product.name; +//if product is or browserpod, add prefix /docs on post url +const demo_url = + productName === "CheerpJ" || productName === "BrowserPod" + ? "https://labs.leaningtech.com/showcase/" + : "/showcase/"; +--- + + + { + demo.data.hero_image && ( + + ) + } +
+

+ {demo.data.title} +

+
+ + { + showMetadata && ( +
+
+
{demo.data.description}
+
+
+ ) + } +
+

+ {demo.data.project_type} +

+ { + demo.data.tags.map((tag) => ( +

+ {tag} +

+ )) + } +
+
diff --git a/packages/astro-theme/components/DemoCardSet.astro b/packages/astro-theme/components/DemoCardSet.astro new file mode 100644 index 00000000..4e9b1546 --- /dev/null +++ b/packages/astro-theme/components/DemoCardSet.astro @@ -0,0 +1,54 @@ +--- +import { getCollection, type CollectionEntry } from "astro:content"; +import DemoCard from "./DemoCard.astro"; +import { productFromUrl } from "../lib/products"; + +interface Props { + // Only show posts if they have at least one of these tags + tags?: string[] | undefined; + + // Exclude posts with these IDs + exclude?: string[] | undefined; +} + +const { tags, exclude } = Astro.props; +const product = productFromUrl(Astro.url); +const productName = typeof product === "undefined" ? "Labs" : product.name; + +function sortCalc(demo: CollectionEntry<"showcase">): number { + let relevancy = + tags && demo.data.tags + ? demo.data.tags.filter((tag) => tags.includes(tag)).length + : 0.1; + if (demo.data.featured) { + relevancy *= 2; + } + return relevancy; +} + +const demos = ( + await getCollection("showcase", (demo) => { + if ( + demo.data.draft || + exclude?.includes(demo.id) || + !(demo.data?.tags?.includes(productName) || productName === "Labs") + ) { + return false; + } else { + return true; + } + }) +) + .sort((a, b) => sortCalc(b) - sortCalc(a)) + .slice(0, 3); +--- + + diff --git a/packages/astro-theme/components/DemoInfo.astro b/packages/astro-theme/components/DemoInfo.astro new file mode 100644 index 00000000..9a48cda7 --- /dev/null +++ b/packages/astro-theme/components/DemoInfo.astro @@ -0,0 +1,116 @@ +--- +import { productFromUrl } from "../lib/products"; +import LinkButton from "../components/LinkButton.astro"; +import Icon from "astro-icon"; + +interface Props { + title?: string; + description?: string | undefined; + niche?: string | undefined; + author?: string | undefined; + project_type?: string | undefined; + demo_url?: string | undefined; + repository_url?: string | undefined; + tags?: string | undefined; +} + +const { + title, + description, + niche, + author, + project_type, + demo_url, + repository_url, + tags, +} = Astro.props; +let tag_string = " "; +{ + tags.map((tag) => (tag_string += " " + tag)); +} +--- + +
+
+

+ {title} + { + description && ( +

+ {description} +

+ ) + } +

+
+ { + demo_url && ( + + ) + } + { + repository_url && ( + + ) + } +
+
+
+
+ + + { + author && ( + + + + + ) + } + { + project_type && ( + + + + + ) + } + { + niche && ( + + + + + ) + } + { + tags && ( + + + + + ) + } + +
Author {author}
Project type {project_type}
Niche {niche}
Technology {tag_string}
+
+
diff --git a/packages/astro-theme/components/ShowcaseList.astro b/packages/astro-theme/components/ShowcaseList.astro index 335ab75c..36d9fb0a 100644 --- a/packages/astro-theme/components/ShowcaseList.astro +++ b/packages/astro-theme/components/ShowcaseList.astro @@ -12,9 +12,9 @@ type Props = CollectionEntry<"showcase">["data"] & { const props = Astro.props; const product = productFromUrl(Astro.url); - -let projects = await getCollection("showcase", ({ data }) => - data?.tags?.includes(product.name) +let projects = await getCollection( + "showcase", + ({ data }) => !product || data?.tags?.includes(product.name) ); if (typeof props.limit == "number") { projects = projects.slice(0, props.limit); @@ -30,9 +30,9 @@ if (typeof props.limit == "number") { href={project.data.url} class="block h-full p-2 border border-bg-700 text-bg-500 rounded-lg shadow-lg hover:translate-y-[-2px] hover:border-bg-600 hover:text-bg-400 transition-all" > - {project.data.heroImage && ( + {project.data.hero_image && ( {project.data.title} + { product.id.match("cheerpx") && ( z.object({ title: z.string(), - description: z.string().optional(), - url: z.string(), - heroImage: image(), + description: z.string(), + demo_url: z.string().optional(), + repository_url: z.string().optional(), + author: z.string(), + project_type: z.string(), + niche: z.string(), + hero_image: image().optional(), + draft: z.boolean().default(false), tags: productTags.optional(), }), }), diff --git a/packages/astro-theme/index.ts b/packages/astro-theme/index.ts index 5af97f60..6f426f56 100644 --- a/packages/astro-theme/index.ts +++ b/packages/astro-theme/index.ts @@ -96,6 +96,15 @@ export default function ThemeIntegration( pattern: `${docsPrefix}/[...slug]`, entrypoint: "@leaningtech/astro-theme/pages/docs/[...slug].astro", }); + //routing for demos showcase + params.injectRoute({ + pattern: "showcase", + entrypoint: "@leaningtech/astro-theme/pages/showcase/index.astro", + }); + params.injectRoute({ + pattern: "showcase/[...slug]", + entrypoint: "@leaningtech/astro-theme/pages/showcase/[...slug].astro", + }); params.updateConfig({ markdown: { remarkPlugins: [[remarkObsidianCallout, {}], remarkReplaceVars], diff --git a/packages/astro-theme/layouts/DemoArticle.astro b/packages/astro-theme/layouts/DemoArticle.astro new file mode 100644 index 00000000..79ebc4b5 --- /dev/null +++ b/packages/astro-theme/layouts/DemoArticle.astro @@ -0,0 +1,150 @@ +--- +import type { CollectionEntry } from "astro:content"; +import Shell from "./Shell.astro"; +import Icon from "astro-icon"; +import { SocialShare } from "astro-social-share"; +import DemoInfo from "../components/DemoInfo.astro"; +import Footer from "../components/Footer.astro"; +import DemoCardSet from "../components/DemoCardSet.astro"; +import LinkButton from "../components/LinkButton.astro"; +import { DISCORD_URL } from "../consts"; +import { Image } from "astro:assets"; +import { productFromUrl } from "../lib/products"; +import ProductNav from "../components/nav/product/Nav.astro"; + +const product = productFromUrl(Astro.url); + +type Props = CollectionEntry<"showcase">["data"] & { + id: CollectionEntry<"showcase">["id"]; + headings: BasicHeading[] | undefined; +}; + +const { + id, + title, + description, + author, + project_type, + niche, + hero_image, + headings, + demo_url, + repository_url, + tags, +} = Astro.props; + +let titleAndSubtitle = title; +if (description) { + titleAndSubtitle += `: ${description}`; +} +--- + + + {product && } +
+
+
+ + Back to showcase + +
+ { + hero_image && ( + + ) + } +
+ + +
+
+ +
+
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ +
+

+ Related posts +

+ +
+ +