Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jelveh committed Mar 3, 2024
0 parents commit fa42b08
Show file tree
Hide file tree
Showing 290 changed files with 99,553 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.DS_Store
node_modules/
*.zip
*.tgz
license.config.json
661 changes: 661 additions & 0 deletions LICENSE.txt

Large diffs are not rendered by default.

78 changes: 78 additions & 0 deletions README.md
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.
3 changes: 3 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const {build} = require("./utils.js")

build();
57 changes: 57 additions & 0 deletions dev-server.js
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;
8 changes: 8 additions & 0 deletions dist/browserconfig.xml
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>
21 changes: 21 additions & 0 deletions dist/bundle.min.css

Large diffs are not rendered by default.

323 changes: 323 additions & 0 deletions dist/bundle.min.js

Large diffs are not rendered by default.

Binary file added dist/favicon.ico
Binary file not shown.
Binary file added dist/favicons/android-icon-144x144.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/android-icon-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/android-icon-36x36.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/android-icon-48x48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/android-icon-72x72.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/android-icon-96x96.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-114x114.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-120x120.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-144x144.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-152x152.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-180x180.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-57x57.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-60x60.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-72x72.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-76x76.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon-precomposed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/apple-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions dist/favicons/browserconfig.xml
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>
Binary file added dist/favicons/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/favicon-96x96.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/favicon.ico
Binary file not shown.
41 changes: 41 additions & 0 deletions dist/favicons/manifest.json
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"
}
]
}
Binary file added dist/favicons/ms-icon-144x144.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/ms-icon-150x150.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/ms-icon-310x310.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/favicons/ms-icon-70x70.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions dist/gui.js
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);
});
}
Binary file added dist/images/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dist/images/wallpaper.webp
Binary file not shown.
41 changes: 41 additions & 0 deletions dist/manifest.json
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"
}
]
}
Loading

0 comments on commit fa42b08

Please sign in to comment.