Skip to content
Permalink
master
Switch branches/tags
Go to file
21 contributors

Users who have contributed to this file

@eldadfux @TorstenDittmann @everly-gif @lohanidamodar @tomer @gewenyu99 @DenverCoder1 @PineappleIOnic @ronfybish @adityaoberai @parshnt @silvia-odwyer

Contributing

We would 鉂わ笍 for you to contribute to Appwrite and help make it better! We want contributing to Appwrite to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, new docs as well as updates and tweaks, blog posts, workshops, and more.

How to Start?

If you are worried or don鈥檛 know where to start, check out our next section explaining what kind of help we could use and where can you get involved. You can reach out with questions to Eldad Fux (@eldadfux) or @appwrite on Twitter, and anyone from the Appwrite team on Discord. You can also submit an issue, and a maintainer can guide you!

Code of Conduct

Help us keep Appwrite open and inclusive. Please read and follow our Code of Conduct.

Submit a Pull Request 馃殌

Branch naming convention is as following

TYPE-ISSUE_ID-DESCRIPTION

example:

doc-548-submit-a-pull-request-section-to-contribution-guide

When TYPE can be:

  • feat - is a new feature
  • doc - documentation only changes
  • cicd - changes related to CI/CD system
  • fix - a bug fix
  • refactor - code change that neither fixes a bug nor adds a feature

All PRs must include a commit message with the changes description!

For聽the聽initial聽start, fork the project and聽use聽git聽clone聽command聽to聽download聽the聽repository聽to聽your聽computer. A standard procedure for working on an issue would be to:

  1. git pull, before creating a new branch, pull the changes from upstream. Your master needs to be up to date.
$ git pull
  1. Create new branch from master like: doc-548-submit-a-pull-request-section-to-contribution-guide
$ git checkout -b [name_of_your_new_branch]
  1. Work - commit - repeat ( be sure to be in your branch )

  2. Before you push your changes, make sure your code follows the PSR12 coding standards , which is the standard Appwrite follows currently. You can easily do this by running the formatter.

composer format <your file path>

Now, go a step further by running the linter by the following command to manually fix the issues the formatter wasn't able to fix.

composer lint <your file path>

This will give you a list of errors for you to rectify , if there is an instance you need more information on the errors being displayed you can pass in additional command line arguments. More list of available arguments can be found here. A very useful command line argument is --report=diff. This will give you the expected changes by the linter for easy fixing of formatting issues.

composer lint --report=diff <your file path>
  1. Push changes to GitHub
$ git push origin [name_of_your_new_branch]
  1. Submit your changes for review If you go to your repository on GitHub, you'll see a Compare & pull request button. Click on that button.
  2. Start a Pull Request Now submit the pull request and click on Create pull request.
  3. Get a code review approval/reject
  4. After approval, merge your PR
  5. GitHub will automatically delete the branch after the merge is done. (they can still be restored).

Setup From Source

To set up a working development environment, just fork the project git repository and install the backend and frontend dependencies using the proper package manager and create run the docker-compose stack.

If you just want to install Appwrite for day-to-day usage and not as a code maintainer use this installation guide.

Please note that these instructions are for setting a functional dev environment. If you want to set up an Appwrite instance to integrate into your app, you should probably try and install Appwrite by using the instructions in the getting started guide or in the main README file.

git clone git@github.com:[YOUR_FORK_HERE]/appwrite.git

cd appwrite

docker compose up -d

Code Autocompletion

To get proper autocompletion for all the different functions and classes in the codebase, you'll need to install Appwrite dependencies on your local machine. You can easily do that with PHP's package manager, Composer. If you don't have Composer installed, you can use the Docker Hub image to get the same result:

docker run --rm --interactive --tty \
  --volume $PWD:/app \
  composer update --ignore-platform-reqs --optimize-autoloader --no-plugins --no-scripts --prefer-dist

User Interface

Appwrite uses an internal micro-framework called Litespeed.js to build simple UI components in vanilla JS and less for compiling CSS code. To apply any of your changes to the UI, use the gulp build or gulp less commands, and restart the Appwrite main container to load the new static files to memory using docker compose restart appwrite.

Get Started

After finishing the installation process, you can start writing and editing code.

Advanced Topics

We love to create issues that are good for beginners and label them as good first issue or hacktoberfest, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn more about some of the more advance topics that will help you master the Appwrite codebase.

Tools and Libs

Learn more at our Technology Stack section.

Network and Protocols
Architecture
Security

Architecture

Appwrite's current structure is a combination of both Monolithic and Microservice architectures, but our final goal, as we grow, is to be using only microservices.


Appwrite

File Structure

.
鈹溾攢鈹 app # Main application
鈹   鈹溾攢鈹 config # Config files
鈹   鈹溾攢鈹 controllers # API & dashboard controllers
鈹   鈹   鈹溾攢鈹 api
鈹   鈹   鈹溾攢鈹 shared
鈹   鈹   鈹斺攢鈹 web
鈹   鈹溾攢鈹 db # DB schemas
鈹   鈹溾攢鈹 sdks # SDKs generated copies (used for generating code examples)
鈹   鈹溾攢鈹 tasks # Server CLI commands
鈹   鈹溾攢鈹 views # HTML server-side templates
鈹   鈹斺攢鈹 workers # Background workers
鈹溾攢鈹 bin # Server executables (tasks & workers)
鈹溾攢鈹 docker # Docker related resources and configs
鈹溾攢鈹 docs # Docs and tutorials
鈹   鈹溾攢鈹 examples
鈹   鈹溾攢鈹 references
鈹   鈹溾攢鈹 services
鈹   鈹溾攢鈹 specs
鈹   鈹斺攢鈹 tutorials
鈹溾攢鈹 public # Public files
鈹   鈹溾攢鈹 dist
鈹   鈹溾攢鈹 fonts
鈹   鈹溾攢鈹 images
鈹   鈹溾攢鈹 scripts
鈹   鈹斺攢鈹 styles
鈹溾攢鈹 src # Supporting libraries (each lib has one role, common libs are released as individual projects)
鈹   鈹斺攢鈹 Appwrite
鈹       鈹溾攢鈹 Auth
鈹       鈹溾攢鈹 Database
鈹       鈹溾攢鈹 Detector
鈹       鈹溾攢鈹 Docker
鈹       鈹溾攢鈹 Event
鈹       鈹溾攢鈹 Extend
鈹       鈹溾攢鈹 Migration
鈹       鈹溾攢鈹 Network
鈹       鈹溾攢鈹 OpenSSL
鈹       鈹溾攢鈹 Realtime
鈹       鈹溾攢鈹 Resque
鈹       鈹溾攢鈹 Specification
鈹       鈹溾攢鈹 Task
鈹       鈹溾攢鈹 Template
鈹       鈹溾攢鈹 URL
鈹       鈹斺攢鈹 Utopia
鈹斺攢鈹 tests # End to end & unit tests
    鈹溾攢鈹 e2e
    鈹溾攢鈹 resources
    鈹斺攢鈹 unit

The Monolithic Part

Appwrite's main API container is designed as a monolithic app. This is a decision we made to allow us to develop the project faster while still being a very small team.

Although the Appwrite API is a monolithic app, it has a very clear separation of concern as each internal service or worker is separated by its container, which will allow us as we grow to start breaking services for better maintenance and scalability.

The Microservice Part

Each container in Appwrite is a microservice on its own. Each service is an independent process that can scale without regard to any of the other services.

Currently, all of the Appwrite microservices are intended to communicate using the TCP protocol over a private network. You should be aware to not expose any of the services to the public-facing network, besides the public port 80 and 443, who, by default, are used to expose the Appwrite HTTP API.

Ports

Appwrite dev version uses ports 80 and 443 as an entry point to the Appwrite API and console. We also expose multiple ports in the range of 9500-9504 for debugging some of the Appwrite containers on dev mode. If you have any conflicts with the ports running on your system, you can easily replace them by editing Appwrite's docker-compose.yml file and executing docker compose up -d command.

Technology Stack

To start helping us to improve the Appwrite server by submitting code, prior knowledge of Appwrite's technology stack can help you with getting started.

Appwrite stack is combined from a variety of open-source technologies and tools. Appwrite backend API is written primarily with PHP version 7 and above on top of the Utopia PHP framework. The Appwrite frontend is built with tools like gulp, less, and litespeed.js. We use Docker as the container technology to package the Appwrite server for easy integration on-cloud, on-premise, or on-localhosts.

Other Technologies

  • Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data)
  • MariaDB - for database storage and queries
  • InfluxDB - for managing stats and time-series based data
  • Statsd - for sending data over UDP protocol (using Telegraf)
  • ClamAV - for validating and scanning storage files
  • Imagemagick - for manipulating and managing image media files.
  • Webp - for better compression of images on supporting clients
  • SMTP - for sending email messages and alerts
  • Resque - for managing data queues and scheduled tasks over a Redis server

Package Managers

Appwrite uses a package manager for managing code dependencies for both backend and frontend development. We try our best to avoid creating any unnecessary, and any new dependency to the project is subjected to a lead developer review and approval.

Many of Appwrite's internal modules are also used as dependencies to allow other Appwrite's projects to reuse them and as a way to contribute them back to the community.

Appwrite uses PHP's Composer for managing dependencies on the server-side and JS NPM for managing dependencies on the frontend side.

Coding Standards

Appwrite is following the PHP-FIG standards. Currently, we are using both PSR-0 and PSR-12 for coding standards and autoloading standards.

We use prettier for our JS coding standards and auto-formatting our code.

Scalability, Speed, and Performance

Appwrite is built to scale. Please keep in mind that the Appwrite stack can run in different environments and different scales.

We wish Appwrite will be as easy to set up and in a single, localhost, and easy to grow to a large environment with dozens and even hundreds of instances.

When contributing code, please take into account the following considerations:

  • Response Time
  • Throughput
  • Requests per Seconds
  • Network Usage
  • Memory Usage
  • Browser Rendering
  • Background Jobs
  • Task Execution Time

Security & Privacy

Security and privacy are extremely important to Appwrite, developers, and users alike. Make sure to follow the best industry standards and practices.

Dependencies

Please avoid introducing new dependencies to Appwrite without consulting the team. New dependencies can be very helpful but also introduce new security and privacy issues, complexity, and impact total docker image size.

Adding a new dependency should have vital value on the product with minimum possible risk.

Introducing New Features

We would 馃挅 you to contribute to Appwrite, but we would also like to make sure Appwrite is as great as possible and loyal to its vision and mission statement 馃檹.

For us to find the right balance, please open an issue explaining your ideas before introducing a new pull request.

This will allow the Appwrite community to have sufficient discussion about the new feature value and how it fits in the product roadmap and vision.

This is also important for the Appwrite lead developers to be able to give technical input and different emphasis regarding the feature design and architecture. Some bigger features might need to go through our RFC process.

Build

To build a new version of the Appwrite server, all you need to do is run the build.sh file like this:

bash ./build.sh X.X.X

Before running the command, make sure you have proper write permissions to the Appwrite docker hub team.

Build for Multicore

docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -t appwrite/appwrite:dev --push .

Build Functions Runtimes

The Runtimes for all supported cloud functions (multicore builds) can be found at the open-runtimes/open-runtimes repository.

Generate SDK

For generating a new console SDK follow the next steps:

  1. Update the console spec file located at app/config/specs/swagger2-<version-number>.console.json using Appwrite Tasks. Run the php app/cli.php specs <version-number> normal command in a running appwrite/appwrite container.
  2. Generate a new SDK using the command php app/cli.php sdks
  3. Change your working dir using cd app/sdks/console-web
  4. Build the new SDK npm run build
  5. Copy iife/sdk.js to appwrite.js
  6. Go back to the root of the project run npm run build

Checklist for Releasing SDKs

Things to remember when releasing SDKs

  • Update the Changelogs in docs/sdks (right now only Dart and Flutter are using these)
  • Update GETTING_STARTED.md in docs/sdks for each SDKs if any changes in the related APIs in there
  • Update SDK versions as required on app/config/platforms.php
  • Generate SDKs using the command php app/cli.php sdks and follow the instructions
  • Release new tags on GitHub repository for each SDKs

Debug

Appwrite uses yasd debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code PHP Debug extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection.

First, you need to create an init file. Duplicate dev/yasd_init.php.stub file and name it dev/yasd_init.php and there change the IP address to your development machine's IP. Without the proper IP address debugger wont connect. And you also need to set DEBUG build arg in appwrite service in docker-compose.yml file.

VS Code Launch Configuration

{
  "name": "Listen for Xdebug",
  "type": "php",
  "request": "launch",
  "port": 9005,
  "pathMappings": {
    "/usr/src/code": "${workspaceRoot}"
  }
}

PHPStorm Setup

In settings, go to Languages & Frameworks > PHP > Debug, there under Xdebug set the debug port to 9005 and enable can accept external connections checkbox.

Tests

To run all tests manually, use the Appwrite Docker CLI from your terminal:

docker compose exec appwrite test

To run unit tests use:

docker compose exec appwrite test /usr/src/code/tests/unit

To run end-2-end tests use:

docker compose exec appwrite test /usr/src/code/tests/e2e

To run end-2-end tests for a spcific service use:

docker compose exec appwrite test /usr/src/code/tests/e2e/Services/[ServiceName]

Benchmarking

You can use WRK Docker image to benchmark the server performance. Benchmarking is extremely useful when you want to compare how the server behaves before and after a change has been applied. Replace [APPWRITE_HOSTNAME_OR_IP] with your Appwrite server hostname or IP. Note that localhost is not accessible from inside the WRK container.

  Options:
    -c, --connections <N>  Connections to keep open
    -d, --duration    <T>  Duration of test
    -t, --threads     <N>  Number of threads to use

    -s, --script      <S>  Load Lua script file
    -H, --header      <H>  Add header to request
        --latency          Print latency statistics
        --timeout     <T>  Socket/request timeout
    -v, --version          Print version details
docker run --rm skandyla/wrk -t3 -c100 -d30  https://[APPWRITE_HOSTNAME_OR_IP]

Code Maintenance

We use some automation tools to help us keep a healthy codebase.

Run Formatter:

# Run on all files
composer format
# Run on single file or folder
composer format <your file path>

Run Linter:

# Run on all files
composer lint
# Run on single file or folder
composer lint <your file path>

Tutorials

From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials:

Other Ways to Help

Pull requests are great, but there are many other areas where you can help Appwrite.

Blogging & Speaking

Blogging, speaking about, or creating tutorials about one of Appwrite鈥檚 many features. Mention @appwrite on Twitter and/or email team@appwrite.io so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our Awesome Appwrite repo on GitHub.

Presenting at Meetups

Presenting at meetups and conferences about your Appwrite projects. Your unique challenges and successes in building things with Appwrite can provide great speaking material. We鈥檇 love to review your talk abstract/CFP, so get in touch with us if you鈥檇 like some help!

Sending Feedbacks & Reporting Bugs

Sending feedback is a great way for us to understand your different use cases of Appwrite better. If you had any issues, bugs, or want to share about your experience, feel free to do so on our GitHub issues page or at our Discord channel.

Submitting New Ideas

If you think Appwrite could use a new feature, please open an issue on our GitHub repository, stating as much information as you can think about your new idea and it's implications. We would also use this issue to gather more information, get more feedback from the community, and have a proper discussion about the new feature.

Improving Documentation

Submitting documentation updates, enhancements, designs, or bug fixes. Spelling or grammar fixes will be very much appreciated.

Helping Someone

Searching for Appwrite on Discord, GitHub, or StackOverflow and helping someone else who needs help. You can also help by teaching others how to contribute to Appwrite's repo!