Official Repository of
Go to file
2024-06-28 17:47:51 +02:00
deployment example ecosystem.yml bind to instead of lohalhost 2024-01-23 22:01:22 +01:00
i18n remove albanian google translate 2024-06-15 19:07:01 +02:00
promotion fix APISocketServer chat broadcast muted check 2022-10-19 00:39:00 +02:00
public add sgn flag 2024-05-01 17:28:41 +02:00
scripts add webpack plugin to list licenses 2024-06-28 17:47:51 +02:00
src if we run on, wipe redis 2024-05-17 22:39:01 +02:00
utils add original map data 2024-02-22 16:46:45 +01:00
.eslintrc.json add eslint rules for react hooks 2024-01-23 20:08:07 +01:00
.gitignore add webpack plugin to list licenses 2024-06-28 17:47:51 +02:00 only send messages from public channels to APIWebSocket 2022-01-12 15:10:24 +01:00
AUTHORS add AUTHORS 2024-04-16 09:21:36 +02:00
babel.config.js remove some seemingly useless babel plugins 2024-01-23 20:08:31 +01:00 reorganize LICENSE into an easier readably form. 2023-07-21 21:16:03 +02:00
COPYING GPL -> APGL 2024-03-09 10:42:52 +01:00
LICENSE add AUTHORS 2024-04-16 09:21:36 +02:00
package-lock.json add webpack plugin to list licenses 2024-06-28 17:47:51 +02:00
package.json add webpack plugin to list licenses 2024-06-28 17:47:51 +02:00 add webpack plugin to list licenses 2024-06-28 17:47:51 +02:00
webpack.config.client.js add webpack plugin to list licenses 2024-06-28 17:47:51 +02:00
webpack.config.server.js add webpack plugin to list licenses 2024-06-28 17:47:51 +02:00



Our translations are hosted on Weblate, information on how to contribute is available under i18n. We very much appreciate any help.

Translation status

To the 2nd anniversary of r/space, pixelplanet takes pixelgames to a new level. Place pixels, create pixelart and fight faction wars. Pixelplanet presents a 65k x 65k large canvas that is a map of the world and can also be seen as 3d globe, you can place pixels where ever you want, build an island, take over another country with a flag or just create pixelart. 30 well chosen colors (decided by polls within the community) are available and you can place a pixel every 3s on an empty space, and 5s on an already set pixel. But pixels can be stacked up to a minute, so you don't have to wait every time.

Pixelplanet receives regular updates and launches events, like a zero second cooldown day on r/place anniversary. We are driven by our community, because placing pixels is more fun together.

Controls: W, A, S, D, click and drag or pan: Move Q, E or scroll or pinch: Zoom Click or tab: Place Pixel screenshot




Checkout repository

git clone
cd pixelplanet

Install packages and build

npm install
npm run build

All needed files to run it got created in ./dist. You can copy it to wherever you want to run pixelplanet.




Configuration takes place in the environment variables that are defined in ecosystem.yml.

Neccessary Configuration

Variable Description Example
PORT Own Port 8080
HOST Own Host "localhost"
REDIS_URL URL:PORT of redis server "redis://localhost:6379"
MYSQL_HOST MySql Host "localhost"
MYSQL_USER MySql User "pixelplanet"
MYSQL_PW MySql Password "sqlpassword"
MYSQL_DATABASE MySql Database "pixelplanet"

Optional Configuration

Variable Description Example
USE_PROXYCHECK Check users for Proxies 0
PROXYCHECK_KEY Key for "asfas-xcsc-ewef-sdfsd"
APISOCKET_KEY Key for API Socket for SpecialAccess™ "SDfasife3"
ADMIN_IDS Ids of users with Admin rights "1,12,3"
CAPTCHA_TIME time in minutes between captchas 30
0: always captcha -1: never captcha
SESSION_SECRET random sting for express sessions "ayylmao"
LOG_MYSQL if sql queries should get logged 0
USE_XREALIP see ngins / CDN section 1
BACKUP_URL url of backup server (see Backup) "http://localhost"
BACKUP_DIR mounted directory of backup server "/mnt/backup/"
HOURLY_EVENT run hourly void event on main canvas 1
USE_MAILER enable to use mail sevicse 0
MAIL_ADDRESS email address for sending mails ""

Social Media Configuration

Variable Description
GUILDED_INVITE Invite to guilded server


  • HOST / PORT is the host on which the ppfun server is listening. In example: If you have a reverse proxy on the same machine, HOST should still be unset or localhost, because it's where the proxy forwards to.
  • to be able to use USE_PROXYCHECK you have to have an account on and set PROXYCHECK_KEY.
  • Admins are users with 0cd and access to Admintoolsin their User Menu
  • You can find out the id of a user by wiriting a message in chat and pinging
  • pixelplanet uses the unix command sendmail for sending verification and password reset mails. If you don't want to set up your own mail server, look into ssmtp, which provides a sendmail interface that forwards to other providers like gmail.
  • default configuartion values can be seen in src/core/config.js
  • The HTML for SocialMedia logins is in src/componets/UserAreaModal.js , delete stuff from there if you don't need it. The HTML for the Help Screen is in src/components/HelpModal.js

Canvas specific configuartion like colors and cooldown is in canvases.json for all canvases. The titles and descriptions of the canvases are in src/canvasesDesc.js for translation reasons. Changing them requires a rebuild. Meaning of some values:

Neccessary canvases Configuration

Key Description
ident Unique character used in the url
size canvas size, power of 2 and between 256 and 65536
bcd Base cooldown for unset pixels
cds Stack time of Cooldown

Optional canvases Configuration

Key Description
pcd Cooldown for placing on set pixels (defaults to same as bcd)
cli Number of leading colors on the palette to ignore (default: 0)
req requieremt to place on the canvas (default: unset)
ranked If pixels on canvas count on player statistic (default: false)
v If 3D voxel canvas (boolean) (default: false)
hid Hidden canvases, can be just seen by pressing P (default: false)
sd Start-date of the canvas (for historical view)
ed end date for historical view (canvas retired)
linkcd id of another canvas to take the cooldown from


  • The canvas size limit can be surpassed by changing the websocket packages in src/socket/packages/ to send chunk coordinates in 16bit.
  • If req is 0, the canvas is only available for registered Useers. If it is a number >0 it is the amount of total pixels placed before a player is allowed to play there. If it is top, then it is only accessible for the Top10 players of the previous day.
  • The colors that are ignored via cli are used for making the canvas (blue ocean and white continents) and to know if the pixel is already set by a user or not.
  • If you want to add a new canvas, be sure that you additionally create public/loading${canvasId}.png, public/assets3d/normal${canvasId}.jpg, public/preview${canvasId}.png and public/assets3d/specular${canvasId}.jpg, check out the existing ones to see what those files are for.


To add more css styles, create a new css file in src/styles based on src/styles/default.css with a filename beginning with "theme-" and rebuild`


Install required packages

npm install

and pm2 is used as process manager to restart on error and provie logging:

npm install -g pm2


  1. Make sure that mysql and redis are running
  2. Start with
pm2 start ecosystem.yml

NOTE: On Windows you might have to prepend npx, like: npx pm2 start ecosystem.yml


General logs are in ~/pm2/log/, you can view them with

pm2 log ppfun

you can flush the logs with

pm2 log flush

Pixel placing logs are in ./log/pixels.logand proxycheck logs in ./log/proxies.log in the directory where you start pixelplaent. They get rotated daily and deleted if >14d old.


pm2 stop ppfun

If using reverse Proxy

If USE_XREALIP is set, we take the IP from the X-Real-Ip header. Use this if you have pixelplanet running behind a reverse proxy like nginx (recommended). Use the nginx set_realip module to give us the client ip on the X-Real-Ip header (and set it up so that just cloudflare are trusted proxy IPs, if you use them, or else players could fake their IP). And be sure to also set X-Forwarded-Host, X-Forwarded-Port and set X-Forwarded-Proto, because we use it for CORS and redirecion.


To have the canvas with all it's components autostart at systemstart, enable mysql, redis (and probably nginx if you use it) according to your system (systemctl enable ...) And then setup pm2 startup with:

pm2 startup

(execute as the user that is running pixelplanet) And follow the printed steps if needed. This will generate a systemctl service file /etc/systemd/system/pm2-pixelplanet.service and enable it. You will have to run pm2 save while the canvas is running to let pm2 know what to start. To make sure that mysql and redis are up when pixelplanet starts, edit this service file and modify the lines: mysql.service redis.service

Hourly Event

Hourly event is an MMORPG style event that launches once in two hours where users have to fight against a growing void that starts at a random position at the main canvas. If they complete it successfully, the whole canvas will have half cooldown for a few minutes.

Backups and Historical View

PixelPlanet includes a backup script that creates full canvas backups daily in the form of PNG tile files and incremential backups all 15min (or whatever you define) that saves PNG tiles with just the differences since the last full daily backup.

It requires a second running redis instance.

The backup script gets built when building pixelplanet and also gets copied to dist/ directory. You can run it with:


Make sure to get the order right, because the backup redis instance will be overwritten every day. Interval is the time in minutes between incremential backups. If interval is undefined, it will just make one backup and then exit. If command is defined, it will be executed after every backup (just one command, with no arguments, like ""), this is useful for synchronisation with a storage server i.e.. Look into utils/backupServer for some scripts and info on how to run it.

You can run it with pm2, just like pixelplanet. An example ecosystem-backup.example.yml file will be located in the dist directory.


  • You do not have to run backups or historical view, it's optional.


Pixelplanet is able to let the user browse through the past with those backups. For this you need to define BACKUP_URL and BACKUP_DIR in your ecosystem.yml for pixelplanet. BACKUP_URL is the URL where the backup folder is available. You have to let another server serve those files or use nginx. BACKUP_DIR is the full path of the local directory where the backup is located (whats set as BACKUP_DIRECTORY in the command of the backup.js).

3D canvas

If v is set and true for a canvas in the canvas.json, it will be a 3D voxel canvas. 3D Canvases can not be seen in Historical View.



Run npm run lint:src to check for code errors and warnings or npm run lint -- ./your/file.js to check a single file.

Compile with source-maps and debug options (but only english language) with

npm run build:dev

ttag is used for handling translations. For server-side rendering the Accept-Language header gets checked and the first locale used and on-the-fly translated (src/core/ttag.js provides the functions for it). On the client-side a seperate bundle for every language gets provided. The language definitions in i18n/template.pot and i18n/template-ssr.pot get updated when doing a full production build with all languages (npm run build)-

To build only specific languages, you can define them with the --langs flag:

npm run build -- --langs de,gr

You can use npm run babel-node ./utils/script.js to execute a script with local babel (path always relative to the root directory).