-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit fa42b08
Showing
290 changed files
with
99,553 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Auto detect text files and perform LF normalization | ||
* text=auto |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.DS_Store | ||
node_modules/ | ||
*.zip | ||
*.tgz | ||
license.config.json |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://github.com/HeyPuter/gui/assets/1715019/ffdc7427-4ed7-41c0-b539-ae7285bd0ffe"></h3> | ||
|
||
<h3 align="center">Desktop Environment in the Browser!</h3> | ||
|
||
<p align="center"> | ||
<a href="https://puter.com/"><strong>« LIVE DEMO »</strong></a> | ||
<br /> | ||
<br /> | ||
<a href="https://puter.com">Puter.com</a> | ||
· | ||
<a href="https://docs.puter.com" target="_blank">SDK</a> | ||
· | ||
<a href="https://discord.com/invite/PQcx7Teh8u">Discord</a> | ||
· | ||
<a href="https://reddit.com/r/puter">Reddit</a> | ||
· | ||
<a href="https://twitter.com/HeyPuter">X (Twitter)</a> | ||
</p> | ||
|
||
<h3 align="center"><img width="700" style="border-radius:5px;" alt="screenshot" src="https://github.com/HeyPuter/gui/assets/1715019/a1579d6a-6a42-4fec-9af2-ca0a31326850"></h3> | ||
|
||
<br/> | ||
|
||
## Getting Started | ||
|
||
```bash | ||
git clone https://github.com/HeyPuter/puter.com | ||
cd puter.com | ||
npm install | ||
npm start | ||
``` | ||
|
||
This will launch Puter in development mode at http://localhost:4000 (or the next available port). | ||
|
||
<br/> | ||
|
||
## Deploy to Production | ||
|
||
Here's a detailed guide on how to run Puter in production: [docs/prod.md](docs/prod.md) | ||
|
||
<br/> | ||
|
||
## FAQ | ||
|
||
### ❓ What's the use case for Puter? | ||
|
||
Puter can be used as: | ||
|
||
- An alternative to Dropbox, Google Drive, OneDrive, etc. with a fresh interface and powerful features. | ||
- Remote desktop environment for remote servers and workstations. | ||
- A platform for building and hosting websites, web apps, and games. | ||
- A friendly, open-source project and community to learn about web development, cloud computing, distributed systems, and much more! | ||
|
||
### ❓ Why isn't Puter built with React, Angular, Vue, etc.? | ||
|
||
For performance reasons, Puter is built with vanilla JavaScript and jQuery. Additionally, we'd like to avoid complex abstractions and to remain in control of the entire stack, as much as possible. | ||
|
||
Also partly inspired by some of our favorite projects that are not built with frameworks: [VSCode](https://github.com/microsoft/vscode), [Photopea](https://www.photopea.com/), and [OnlyOffice](https://www.onlyoffice.com/). | ||
|
||
### ❓ Why jQuery? | ||
|
||
Puter interacts directly with the DOM and jQuery provides an elegant yet powerful API to manipulate the DOM, handle events, and much more. It's also fast, mature, and battle-tested. | ||
|
||
<br/> | ||
|
||
## Credits | ||
|
||
The default wallpaper is created by [Milad Fakurian](https://unsplash.com/photos/blue-orange-and-yellow-wallpaper-E8Ufcyxz514) and published on [Unsplash](https://unsplash.com/). | ||
|
||
Icons by [Papirus](https://github.com/PapirusDevelopmentTeam/papirus-icon-theme) under GPL-3.0 license. | ||
|
||
Icons by [Iconoir](https://iconoir.com/) under MIT license. | ||
|
||
Icons by [Elementary Icons](https://github.com/elementary/icons) under GPL-3.0 license. | ||
|
||
Icons by [Tabler Icons](https://tabler.io/) under MIT license. | ||
|
||
Icons by [bootstrap-icons](https://icons.getbootstrap.com/) under MIT license. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const {build} = require("./utils.js") | ||
|
||
build(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const express = require("express"); | ||
const { generateDevHtml, build } = require("./utils.js"); | ||
const { argv } = require('node:process'); | ||
const chalk = require('chalk'); | ||
|
||
const app = express(); | ||
let port = 4000; // Starting port | ||
const maxAttempts = 10; // Maximum number of ports to try | ||
const env = argv[2] ?? "dev"; | ||
|
||
const startServer = (attempt) => { | ||
if (attempt > maxAttempts) { | ||
console.error(chalk.red(`ERROR: Unable to find an available port after ${maxAttempts} attempts.`)); | ||
return; | ||
} | ||
|
||
app.listen(port, () => { | ||
console.log("\n-----------------------------------------------------------\n"); | ||
console.log(`Puter is now live at: `, chalk.underline.blue(`http://localhost:${port}`)); | ||
console.log("\n-----------------------------------------------------------\n"); | ||
}).on('error', (err) => { | ||
if (err.code === 'EADDRINUSE') { // Check if the error is because the port is already in use | ||
console.error(chalk.red(`ERROR: Port ${port} is already in use. Trying next port...`)); | ||
port++; // Increment the port number | ||
startServer(attempt + 1); // Try the next port | ||
} | ||
}); | ||
}; | ||
|
||
// Start the server with the first attempt | ||
startServer(1); | ||
|
||
// build the GUI | ||
build(); | ||
|
||
app.get(["/", "/app/*", "/action/*"], (req, res) => { | ||
res.send(generateDevHtml({ | ||
env: env, | ||
api_origin: "https://api.puter.com", | ||
title: "Puter", | ||
max_item_name_length: 150, | ||
require_email_verification_to_publish_website: false, | ||
short_description: `Puter is a privacy-first personal cloud that houses all your files, apps, and games in one private and secure place, accessible from anywhere at any time.`, | ||
})); | ||
}) | ||
app.use(express.static('./')); | ||
|
||
if(env === "prod"){ | ||
// make sure to serve the ./dist/ folder maps to the root of the website | ||
app.use(express.static('./dist/')); | ||
} | ||
|
||
if(env === "dev"){ | ||
app.use(express.static('./src/')); | ||
} | ||
|
||
module.exports = app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<browserconfig> | ||
<msapplication> | ||
<tile> | ||
<square70x70logo src="./favicons/ms-icon-70x70.png"/> | ||
<square150x150logo src="./favicons/ms-icon-150x150.png"/> | ||
<square310x310logo src="./favicons/ms-icon-310x310.png"/> | ||
<TileColor>#ffffff</TileColor></tile></msapplication></browserconfig> |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "App", | ||
"icons": [ | ||
{ | ||
"src": "\/android-icon-36x36.png", | ||
"sizes": "36x36", | ||
"type": "image\/png", | ||
"density": "0.75" | ||
}, | ||
{ | ||
"src": "\/android-icon-48x48.png", | ||
"sizes": "48x48", | ||
"type": "image\/png", | ||
"density": "1.0" | ||
}, | ||
{ | ||
"src": "\/android-icon-72x72.png", | ||
"sizes": "72x72", | ||
"type": "image\/png", | ||
"density": "1.5" | ||
}, | ||
{ | ||
"src": "\/android-icon-96x96.png", | ||
"sizes": "96x96", | ||
"type": "image\/png", | ||
"density": "2.0" | ||
}, | ||
{ | ||
"src": "\/android-icon-144x144.png", | ||
"sizes": "144x144", | ||
"type": "image\/png", | ||
"density": "3.0" | ||
}, | ||
{ | ||
"src": "\/android-icon-192x192.png", | ||
"sizes": "192x192", | ||
"type": "image\/png", | ||
"density": "4.0" | ||
} | ||
] | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
window.gui_env="prod"; | ||
|
||
window.puter_gui_enabled = true; | ||
/** | ||
* Initializes and configures the GUI (Graphical User Interface) settings based on the provided options. | ||
* | ||
* The function sets global variables in the window object for various settings such as origins and domain names. | ||
* It also handles loading different resources depending on the environment (development or production). | ||
* | ||
* @param {Object} options - Configuration options to initialize the GUI. | ||
* @param {string} [options.gui_origin='https://puter.com'] - The origin URL for the GUI. | ||
* @param {string} [options.api_origin='https://api.puter.com'] - The origin URL for the API. | ||
* @param {number} [options.max_item_name_length=500] - Maximum allowed length for an item name. | ||
* @param {boolean} [options.require_email_verification_to_publish_website=true] - Flag to decide whether email verification is required to publish a website. | ||
* | ||
* @property {string} [options.app_domain] - Extracted domain name from gui_origin. It's derived automatically if not provided. | ||
* @property {string} [window.gui_env] - The environment in which the GUI is running (e.g., "dev" or "prod"). | ||
* | ||
* @returns {Promise<void>} Returns a promise that resolves when initialization and resource loading are complete. | ||
* | ||
* @example | ||
* window.gui({ | ||
* gui_origin: 'https://myapp.com', | ||
* api_origin: 'https://myapi.com', | ||
* max_item_name_length: 250 | ||
* }); | ||
*/ | ||
|
||
window.gui = async function(options){ | ||
options = options ?? {}; | ||
// app_origin is deprecated, use gui_origin instead | ||
window.gui_origin = options.gui_origin ?? options.app_origin ?? `https://puter.com`; | ||
window.app_domain = options.app_domain ?? new URL(window.gui_origin).hostname; | ||
window.hosting_domain = options.hosting_domain ?? 'puter.site'; | ||
window.api_origin = options.api_origin ?? "https://api.puter.com"; | ||
window.max_item_name_length = options.max_item_name_length ?? 500; | ||
window.require_email_verification_to_publish_website = options.require_email_verification_to_publish_website ?? true; | ||
|
||
// Add Puter.JS | ||
await loadScript('https://js.puter.com/v2/'); | ||
|
||
// DEV: Load the initgui.js file if we are in development mode | ||
if(!window.gui_env || window.gui_env === "dev"){ | ||
await loadScript('/initgui.js', {isModule: true}); | ||
} | ||
|
||
// PROD: load the minified bundles if we are in production mode | ||
// note: the order of the bundles is important | ||
// note: Build script will prepend `window.gui_env="prod"` to the top of the file | ||
else if(gui_env === "prod"){ | ||
// Load the minified bundles | ||
await loadCSS('/dist/bundle.min.css'); | ||
await loadScript('/dist/bundle.min.js'); | ||
} | ||
|
||
// 🚀 Launch the GUI 🚀 | ||
initgui(); | ||
} | ||
|
||
/** | ||
* Dynamically loads an external JavaScript file. | ||
* @param {string} url The URL of the external script to load. | ||
* @param {Object} [options] Optional configuration for the script. | ||
* @param {boolean} [options.isModule] Whether the script is a module. | ||
* @param {boolean} [options.defer] Whether the script should be deferred. | ||
* @param {Object} [options.dataAttributes] An object containing data attributes to add to the script element. | ||
* @returns {Promise} A promise that resolves once the script has loaded, or rejects on error. | ||
*/ | ||
window.loadScript = async function(url, options = {}) { | ||
return new Promise((resolve, reject) => { | ||
const script = document.createElement('script'); | ||
script.src = url; | ||
|
||
// Set default script loading behavior | ||
script.async = true; | ||
|
||
// Handle if it is a module | ||
if (options.isModule) { | ||
script.type = 'module'; | ||
} | ||
|
||
// Handle defer attribute | ||
if (options.defer) { | ||
script.defer = true; | ||
script.async = false; // When "defer" is true, "async" should be false as they are mutually exclusive | ||
} | ||
|
||
// Add arbitrary data attributes | ||
if (options.dataAttributes && typeof options.dataAttributes === 'object') { | ||
for (const [key, value] of Object.entries(options.dataAttributes)) { | ||
script.setAttribute(`data-${key}`, value); | ||
} | ||
} | ||
|
||
// Resolve the promise when the script is loaded | ||
script.onload = () => resolve(); | ||
|
||
// Reject the promise if there's an error during load | ||
script.onerror = (error) => reject(new Error(`Failed to load script at url: ${url}`)); | ||
|
||
// Append the script to the body | ||
document.body.appendChild(script); | ||
}); | ||
}; | ||
|
||
/** | ||
* Dynamically loads an external CSS file. | ||
* @param {string} url The URL of the external CSS to load. | ||
* @returns {Promise} A promise that resolves once the CSS has loaded, or rejects on error. | ||
*/ | ||
window.loadCSS = async function(url) { | ||
return new Promise((resolve, reject) => { | ||
const link = document.createElement('link'); | ||
link.rel = 'stylesheet'; | ||
link.href = url; | ||
|
||
link.onload = () => { | ||
resolve(); | ||
}; | ||
|
||
link.onerror = (error) => { | ||
reject(new Error(`Failed to load CSS at url: ${url}`)); | ||
}; | ||
|
||
document.head.appendChild(link); | ||
}); | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "App", | ||
"icons": [ | ||
{ | ||
"src": "/favicons/android-icon-36x36.png", | ||
"sizes": "36x36", | ||
"type": "image/png", | ||
"density": "0.75" | ||
}, | ||
{ | ||
"src": "/favicons/android-icon-48x48.png", | ||
"sizes": "48x48", | ||
"type": "image/png", | ||
"density": "1.0" | ||
}, | ||
{ | ||
"src": "/favicons/android-icon-72x72.png", | ||
"sizes": "72x72", | ||
"type": "image/png", | ||
"density": "1.5" | ||
}, | ||
{ | ||
"src": "/favicons/android-icon-96x96.png", | ||
"sizes": "96x96", | ||
"type": "image/png", | ||
"density": "2.0" | ||
}, | ||
{ | ||
"src": "/favicons/android-icon-144x144.png", | ||
"sizes": "144x144", | ||
"type": "image/png", | ||
"density": "3.0" | ||
}, | ||
{ | ||
"src": "/favicons/android-icon-192x192.png", | ||
"sizes": "192x192", | ||
"type": "image/png", | ||
"density": "4.0" | ||
} | ||
] | ||
} |
Oops, something went wrong.