1. Project Overview & Quickstart (alextselegidis/easyappointments)
File: README.md
text<a href="https://easyappointments.org">
</a>
Easy!Appointments
<a href="https://easyappointments.org">
</a>
Easy!AppointmentsA powerful, self-hosted appointment scheduling platform built for flexibility.
๐ Why Easy!Appointments
Easy!Appointments is an open-source scheduling system that gives you full control over your booking workflow.
It is designed to adapt to your business โ whether you need simple appointment booking or more advanced scheduling logic.
Key advantages:
- Fully self-hosted โ your data stays under your control
- Highly customizable and flexible
- Integrates with your existing website and database
- Free for both personal and commercial use
โจ Features
Built to support a wide range of scheduling needs:
- Appointment and customer management
- Service and provider organization
- Working plans and booking rules
- Google Calendar synchronization
- Email notification system
- Multi-language interface
- Self-hosted deployment
- Active open-source community
โก Quick Start (Development)
Clone and run the project locally using the provided Docker Compose environment:
# Clone the repository
git clone https://github.com/alextselegidis/easyappointments.git
# Navigate into the project
cd easyappointments
# Start the Docker environment
docker compose upThen open a second terminal and enter the application container:
docker compose exec app bashInside the container, install dependencies:
npm install && composer installStart the development watcher:
npm startBuild production assets:
npm run buildNote: Works on Windows (WSL recommended), macOS, and Linux using Docker Compose.
๐๏ธ Installation (Production)
Requirements
- Apache or Nginx
- PHP 8.2+
- MySQL database
Steps
- Create a database (or use an existing one)
- Upload the
easyappointmentsfolder to your server - Ensure the
storagedirectory is writable - Rename
config-sample.phptoconfig.php - Update configuration values
- Open the application in your browser and follow the setup wizard
Once completed, the system is ready to use.
๐ Resources
- Website: https://easyappointments.org
- Issues: https://github.com/alextselegidis/easyappointments/issues
- Support Group: https://groups.google.com/forum/#!forum/easy-appointments
- Discord: https://discord.com/invite/UeeSkaw
๐ License
- Code: GPL v3.0
- Content: CC BY 3.0
๐ค Author
- Website: https://alextselegidis.com
- GitHub: https://github.com/alextselegidis
- Twitter: https://twitter.com/AlexTselegidis
๐ฅ More Projects
File: docs/caldav-calendar-sync.md
CalDAV Calendar Sync
This guide explains how to set up a local CalDAV server (Baikal) for testing calendar sync with Easy!Appointments.
Note: This guide uses the Docker development setup from
docker-compose.yml.
Setting Up Baikal
Baikal is a free, self-hosted calendar server. In the Docker setup, it runs at http://localhost:8100.
First-Time Setup
- Open http://localhost:8100 in your browser.
- You'll see a setup form. Fill it in:
- Time zone: Choose your local time zone (must match Easy!Appointments).
- WebDAV authentication type: Select Basic.
- Admin password: Set something simple like
adminfor local testing.
- On the next page, keep the default settings and submit.
Create a Test User
- After setup, go to Users and resources in Baikal.
- Create a new user (e.g. username:
testuser, password:testpass).
Connecting Easy!Appointments to Baikal
- In Easy!Appointments, go to the Calendar page.
- Click Enable Sync โ CalDAV.
- Enter the following:
- URL:
http://baikal/dav.php/calendars/testuser/default/(replacetestuserwith your Baikal username) - Username:
testuser - Password:
testpass
- URL:
That's it โ your appointments will now sync with the Baikal CalDAV server.
This document applies to Easy!Appointments v1.6.0.
File: docs/console.md
Console
Easy!Appointments includes a set of command-line tools you can run from a terminal. These are useful for automating tasks like backups and database updates.
Before You Start
Make sure PHP is installed and available in your terminal. You can check by running:
php -vThis should print the PHP version number. If it doesn't, you need to install PHP or add it to your system's PATH.
Available Commands
All commands start with php index.php console and are run from the Easy!Appointments root folder.
Migrate
Updates your database to the latest version:
php index.php console migrateTo reset the database and re-run all migrations from scratch:
php index.php console migrate freshWarning: The
freshoption deletes all existing data.
Seed
Adds sample data (a test admin, provider, customer, and service) so you can try things out:
php index.php console seedInstall
Runs the installer from the command line (instead of using the browser):
php index.php console installMake sure you've already filled in your config.php file before running this.
Backup
Creates a backup of your data in the storage/backups folder:
php index.php console backupTo save the backup to a different folder:
php index.php console backup /path/to/your/folderSync
Syncs calendars for all providers who have calendar sync enabled:
php index.php console syncTip: Set this up as a cron job to run automatically (e.g. every hour) so your calendars stay up to date without manual work.
Cleanup
Runs storage and data cleanup tasks:
php index.php console cleanupThis command removes expired sessions, old logs and cache files, and deletes old customer data based on your configured data retention settings.
Tip: Add this command to a cron job so cleanup runs automatically.
Help
Shows a summary of all available commands:
php index.php console helpThis document applies to Easy!Appointments v1.6.0.
File: docs/docker.md
Docker
Docker lets you run Easy!Appointments on your computer without installing Apache, PHP, or MySQL manually. Everything runs inside containers โ isolated mini-environments that are easy to start and stop.
Getting Started
- Make sure you have Docker installed.
- Clone or download the project.
- Edit the
config.phpfile in the root folder to match the Docker setup:
class Config {
// GENERAL SETTINGS
const BASE_URL = 'http://localhost';
const LANGUAGE = 'english';
const DEBUG_MODE = TRUE;
// DATABASE SETTINGS
const DB_HOST = 'mysql';
const DB_NAME = 'easyappointments';
const DB_USERNAME = 'user';
const DB_PASSWORD = 'password';
// GOOGLE CALENDAR SYNC
const GOOGLE_SYNC_FEATURE = FALSE;
const GOOGLE_CLIENT_ID = '';
const GOOGLE_CLIENT_SECRET = '';
}- Start everything with:
docker compose upWhat's Included
Once running, you can access these services in your browser:
| Service | URL | Credentials |
|---|---|---|
| Easy!Appointments | http://localhost | (your admin account) |
| phpMyAdmin (database manager) | http://localhost:8080 | root / secret |
| Mailpit (email testing) | http://localhost:8025 | (no login needed) |
| Baikal (CalDAV testing) | http://localhost:8100 | admin / admin |
| phpLDAPadmin (LDAP testing) | http://localhost:8200 | cn=admin,dc=example,dc=org / admin |
CalDAV Sync with Baikal
To test CalDAV syncing locally:
- Open Baikal at http://localhost:8100 and create a new user.
- In Easy!Appointments, click Enable Sync โ CalDAV and enter:
- URL:
http://baikal/dav.php/calendars/<your-username>/default/ - Username: your Baikal username
- Password: your Baikal password
- URL:
LDAP
OpenLDAP runs on the openldap container (ports 389 and 636). You can manage it through phpLDAPadmin at http://localhost:8200.
Note: This Docker setup is for development only. Don't use it in production. For a production Docker image, see: https://github.com/alextselegidis/easyappointments-docker
This document applies to Easy!Appointments v1.6.0.
File: docs/faq.md
FAQ
How do I check that my server has Apache, PHP, and MySQL installed?
Easy!Appointments needs three things on your server: Apache (the web server), PHP (the programming language), and MySQL (the database). You also need the PHP curl extension and the Apache mod_rewrite module enabled.
Two ways to check:
- Ask your hosting company โ they can confirm what's installed.
- Create a test file โ make a file called
phpinfo.phpin your website's root folder with this content:Then openphp<?php phpinfo(); ?>http://your-domain.com/phpinfo.phpin your browser. It will show everything installed on your server. Delete this file when you're done for security reasons.
How do I create a Google Calendar API key?
See the Google Calendar Sync guide for detailed step-by-step instructions.
The Installation Page Is Not Working
This usually happens for one of two reasons:
1. Wrong config settings
Open config.php and double-check:
BASE_URLis set to your exact installation URL (e.g.http://your-domain.com/easyappointments)- Your database name, username, and password are correct
2. Server is blocking requests
Some hosting providers need an .htaccess fix. Create or edit the .htaccess file in your installation folder and add:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]If that doesn't work, check the Apache error log and the browser console (press F12 โ Console tab) for error messages. Contact your hosting company with those details.
The Booking Page Won't Show Any Available Hours
If no hours appear at all:
This is usually a server issue. Check the Apache error log and browser console (F12 โ Console) for errors. Contact your hosting company with the details you find.
If you see "There are no available appointment hours for the selected date":
This often happens because the default working plan includes breaks that don't leave enough room for your service. For example, if your service lasts 3โ4 hours but there are lunch breaks in between, no slot is long enough.
Fix: Go to Users โ Providers, select the provider, and adjust their working plan. Remove or shorten breaks so there's enough continuous time for your services.
Installing on a Subdomain Doesn't Show Available Hours
If Easy!Appointments is on a subdomain like http://book.mysite.com, make sure BASE_URL in config.php uses the subdomain URL โ not the folder path.
Correct: BASE_URL = 'http://book.mysite.com'
Wrong: BASE_URL = 'http://mysite.com/book'
Using the wrong URL causes a browser security error that blocks the booking page from loading appointment hours.
How Do I Change the Time Slot Interval?
By default, available appointment times are shown every 15 minutes (e.g. 9:00, 9:15, 9:30โฆ). You can change this from the backend service settings by editing the Slot Interval (Minutes) field.
I'm Getting a Timezone Warning
If you see an error like DateTime::__construct(): It is not safe to rely on the system's timezone settings..., it means PHP doesn't have a timezone set.
Fix: Open your php.ini file and set the timezone:
date.timezone = America/New_YorkUse your own timezone from the PHP timezone list.
If you can't edit php.ini, add this line to the top of index.php:
date_default_timezone_set('America/New_York'); // Use your own timezoneHow Do I Use Caddy Instead of Apache?
If you prefer Caddy as your web server:
- Install Caddy
- Install PHP-FPM:
sudo apt install php-fpm - Set up Easy!Appointments in a folder (e.g.
/var/www/html/easyappointments) - Add this to
/etc/caddy/Caddyfile:
easyappointments.example.com {
root * /var/www/html/easyappointments
encode gzip zstd
php_fastcgi unix//run/php/php-fpm.sock
file_server
}- Restart Caddy:
sudo systemctl restart caddy.service
This document applies to Easy!Appointments v1.6.0.
File: docs/get-involved.md
Get Involved
Easy!Appointments is open source, and there are several ways you can help make it better.
Report Bugs
Found something broken? Let us know! The more bugs we find and fix, the more reliable the app becomes for everyone.
Suggest Features
Have an idea for a new feature or improvement? We'd love to hear it. Submit your suggestions through the E!A Submission Form.
Help Translate
The app is already available in many languages, but new features need new translations. You can submit your translations via a pull request on GitHub or email them to [email protected].
Share Your Feedback
Take a few minutes to fill out the E!A Feedback Form. Your experience helps shape the future of the project.
This document applies to Easy!Appointments v1.6.0.
File: docs/google-calendar-sync.md
Google Calendar Sync
Easy!Appointments can sync appointments with Google Calendar in both directions. When a provider links their Google Calendar, any changes made in either system will be reflected in the other.
What You Need
- A working Easy!Appointments installation with at least one service and provider set up.
- A Google account.
Step 1: Create Google API Credentials
You need to tell Google that your Easy!Appointments installation is allowed to access calendar data.
- Go to the Google Cloud Console and create a new project (or select an existing one).
- In the project dashboard, go to APIs & Services > Library and search for Google Calendar API. Click on it and press Enable.
- Go to APIs & Services > Credentials and click Create Credentials > OAuth client ID.
- If prompted, fill in the OAuth consent screen information first.
- Select Web Application as the application type and give it a name.
- Under Authorized JavaScript origins, add your domain (just the domain, e.g.
http://mywebsite.com). - Under Authorized redirect URIs, add:Replacetext
https://your-domain.com/easyappointments/index.php/google/oauth_callbackyour-domain.com/easyappointmentswith your actual installation URL. - Click Create. Google will show you a Client ID and Client Secret โ copy both.
Step 2: Configure Credentials in Easy!Appointments
You can now configure the Google Client ID and Client Secret directly from the Easy!Appointments user interface (Backend Settings โ Google Calendar section).
As an alternative, you can still define them in config.php:
const GOOGLE_SYNC_FEATURE = TRUE;
const GOOGLE_CLIENT_ID = 'your-client-id-here';
const GOOGLE_CLIENT_SECRET = 'your-client-secret-here';Step 3: Link a Provider's Google Calendar
- Log in to the Easy!Appointments backend and go to the Calendar page.
- Select a provider and click Enable Sync.
- A Google sign-in window will appear. Log in with the provider's Google account and grant permission.
- The sync is now active!
Good to Know
- Sync is triggered from the Easy!Appointments backend or whenever appointments change.
- Each provider can only be linked to one Google Calendar account.
- Recurring events are supported during sync, but they cannot be created or managed directly from Easy!Appointments.
Useful Links
This document applies to Easy!Appointments v1.6.0.
File: docs/installation-guide.md
Installation Guide
This guide walks you through installing and setting up Easy!Appointments on your server.
What You Need
Easy!Appointments runs on a web server, just like a regular website. Before you begin, make sure you have:
- Apache (v2.4 or newer) โ the web server software
- PHP (v8.2 or newer) โ the programming language that runs the app
- MySQL (v5.7 or newer) โ the database that stores your data
Most web hosting companies already include all three. If you're installing on your own computer, use a free bundle like XAMPP, MAMP, or WAMP โ they install everything for you.
If you plan to use Google Calendar sync, you'll also need the php_curl PHP extension enabled.
Installation Steps
1. Create a Database
You need a MySQL database to store appointment data. If your hosting plan includes one, use that. Otherwise, create a new one through your hosting control panel (e.g. cPanel or phpMyAdmin). Write down the database name, username, and password โ you'll need them soon.
2. Upload the Files
Upload the Easy!Appointments files to your server using FTP or your hosting's file manager. Place them in a folder like easyappointments, appointments, or book.
Take note of the URL. For example, if you uploaded to a folder called easyappointments, the URL will look like: http://your-domain.com/easyappointments
3. Make the Storage Folder Writable
The storage folder is where the app saves logs and temporary files. It needs write permissions. If you're on Linux, you can run:
chmod -R 755 storageOr set permissions through your hosting's file manager.
4. Edit the Config File
Open the config.php file in the root folder and fill in:
- BASE_URL โ the URL to your installation (from Step 2)
- DB_HOST โ usually
localhost - DB_NAME โ your database name
- DB_USERNAME โ your database username
- DB_PASSWORD โ your database password
You can also add Google Calendar API keys here if you want to use that feature later.
5. Run the Installer
Open your browser and go to your Easy!Appointments URL (e.g. http://your-domain.com/easyappointments). You'll see a setup wizard. Fill in your admin account details and company info, then click Install.
That's it โ Easy!Appointments is now installed!
Setting Up Your Business
After installation, the app comes with some test data. Here's how to set things up for your business:
1. Set Your Working Hours
Go to the backend by visiting http://your-url/index.php/calendar and log in. Click Settings โ Business Logic and set your company's working days and hours. Click Save. This becomes the default schedule for any new providers you add.
2. Add Your Services
Click Services and add the services your customers can book (e.g. "Haircut", "Consultation", "Massage"). Fill in the name, duration, and price for each one. You can organize services into categories if you like.
3. Add Your Providers
Click Users โ Providers and add the people who provide your services. For each provider, set their working hours and which services they offer.
Tip: If you run a one-person business, just create a single provider with your company name.
4. Add Secretaries (Optional)
If someone manages bookings for your team, click the Secretaries tab and add them. Choose which providers they can manage.
5. You're Ready!
Click Go To Booking Page at the bottom of the page to see your public booking page. Try creating a test appointment โ it will show up in your Calendar.
Finally, add a link to your website (e.g. "Book an Appointment") that points to your Easy!Appointments URL so customers can find it.
Happy Bookin'!
This document applies to Easy!Appointments v1.6.0.
File: docs/ldap.md
LDAP Integration
LDAP lets you import users from a central directory (like your company's employee directory) into Easy!Appointments. It also enables single sign-on (SSO), so users can log in with their existing company credentials.
Note: This guide uses the Docker development setup. For production, replace the example values with your own LDAP server details.
Local Development Setup (Docker)
The Docker setup includes OpenLDAP and phpLDAPadmin, ready to use with no extra configuration.
| Service | URL | Credentials |
|---|---|---|
| phpLDAPadmin | http://localhost:8200 | cn=admin,dc=example,dc=org / admin |
| OpenLDAP | openldap:389 (inside Docker) |
Same as above |
Creating a Test User in phpLDAPadmin
Before you can log in via LDAP, the directory needs at least one user entry. With a fresh OpenLDAP container the tree is empty, so you have to create a group first (otherwise phpLDAPadmin's user form leaves the GID Number dropdown empty and refuses to save) and then the user.
1. Create a group
- Open phpLDAPadmin at http://localhost:8200 and log in with
cn=admin,dc=example,dc=org/admin. - In the tree on the left, click
dc=example,dc=orgโ Create a child entry. - Choose the Generic: Posix Group template.
- Fill in:
- Group (cn):
users - GID Number: leave the suggested value (e.g.
500) or set10000.
- Group (cn):
- Click Create Object โ Commit.
2. Create the user account
- Click
dc=example,dc=orgโ Create a child entry again. - Choose the Generic: User Account template.
- Fill in:
- First name:
Jane - Last name:
Doe - Common Name:
Jane Doe - User ID (uid):
janedoeโ this is what you will type at the EA login screen. - GID Number: pick the
usersgroup you just created. - Home directory: leave the default.
- Login shell:
/bin/bash(or any value). - Password:
password(choose SSHA as the hash type).
- First name:
- Click Create Object โ Commit.
- Open the new entry and copy its full Distinguished Name, e.g.
cn=Jane Doe,dc=example,dc=org. You will need it in the next step.
Tip: If you don't need POSIX attributes, you can skip the group and create the user with only the
inetOrgPerson+topobject classes. The GID dropdown then disappears entirely.
3. Link the LDAP entry to an Easy!Appointments user
- Log in to the EA backend as admin.
- Open Users โ Providers (or Admins / Secretaries depending on the role) and edit Jane Doe.
- Set the Username field to the same value as the LDAP
uid, e.g.janedoe. The username must match exactly โ EA looks up the account by username before it ever attempts an LDAP bind, so a mismatch results in a generic "invalid credentials" response. - Paste the DN from step 2.5 into the LDAP DN field.
- Save the user.
- You can now log in at the EA login screen with
janedoe/password.
Enabling LDAP in Easy!Appointments
- Log in to the backend.
- Go to Settings โ Integrations โ LDAP.
- Turn on the integration and fill in the connection settings:
| Setting | Docker Value | Description |
|---|---|---|
| Host | openldap |
Your LDAP server address |
| Port | 389 |
Your LDAP server port |
| User DN | cn=admin,dc=example,dc=org |
The admin account used to connect |
| Password | admin |
The admin account password |
| Base DN | dc=example,dc=org |
Where to start searching for users |
| Filter | (default is fine) | Controls which LDAP entries are returned. The {{KEYWORD}} placeholder is replaced with your search term |
Field Mapping
You can map LDAP fields to Easy!Appointments fields so that user information is automatically filled in when importing. This is a JSON object, for example:
{"first_name": "givenName", "last_name": "sn", "email": "mail"}Importing Users
- On the LDAP settings page, use the search box to find users in your LDAP directory.
- Click Import on a user to open a form with their details pre-filled.
- Review and adjust the information, then save.
Note: Backend users (admins, secretaries, providers) need a local password before import. If you only plan to use LDAP login, set a long random password.
Make sure the LDAP DN field points to the correct LDAP entry, and the username matches the LDAP username (usually the cn attribute).
Single Sign-On (SSO)
Once LDAP is enabled, users can log in with their LDAP credentials:
- Easy!Appointments first tries the local password.
- If that doesn't work, it checks the password against LDAP.
- If the LDAP password matches, the user is logged in.
For this to work:
- The user must already be imported into Easy!Appointments.
- The username must match between both systems.
- The LDAP DN field must point to the correct LDAP entry.
This document applies to Easy!Appointments v1.6.0.
File: docs/manage-translations.md
Manage Translations
Easy!Appointments supports multiple languages. You can modify existing translations or add your own.
How Translations Work
Each language has its own folder inside /application/language/ (e.g. english, german, french). Inside each folder, the translations_lang.php file contains all the text shown in the app.
Adding a New Translation
1. Create the Language Folder
Inside /application/language/, create a new folder named after your language (e.g. french). Copy all files from the english folder into it.
Also copy the migration_lang.php file from another language folder (e.g. german) โ the app needs this file to run database updates.
2. Translate the Strings
Open translations_lang.php in your new folder and replace the English text with your translation:
$lang['page_title'] = 'Your translation here!';Keep the key names (the part in square brackets) exactly the same โ only change the text after the = sign.
3. Register Your Translation
Open /application/config/config.php and find the available_languages array. Add your language to it:
$config['available_languages'] = ['english', 'german', 'greek', 'your-language'];To change the default language for all users, update:
$config['language'] = 'english'; // Change to your languageSharing Your Translation
If you'd like to contribute your translation to the project, you can submit a pull request on GitHub or email it to [email protected].
This document applies to Easy!Appointments v1.6.0.
2. Official Technical Reference & Guides (alextselegidis/alextselegidis.github.io)
text<a href="https://alextselegidis.com">
</a>
Personal Website (CSS-only Implementation)
<a href="https://alextselegidis.com">
</a>
Personal Website (CSS-only Implementation)Welcome to my personal website repository, holding the code behind [alextselegidis.com](https://alextselegidis.com)
About
The main purpose of this repository is to demonstrate the creation of a modern web design, without the use of
JavaScript. The final result is a lightweight web page with sleek design and animations that solely work with CSS.
The project is using PostCSS to process the styles with supporting plugins such as Autoprefixes, Precss and Color
Functions processing the final stylesheet.
Setup
To clone and run this application, you'll need Git and Node.js
(which comes with npm) installed on your computer. From your command line:
# Clone this repository
$ git clone https://github.com/alextselegidis/alextselegidis.github.io.git
# Go into the repository
$ cd alextselegidis.github.io
# Install dependencies
$ npm install
# Run the app
$ npm startNote: If you're using Linux Bash for Windows, see this guide or use node from the command prompt.
License
Code Licensed Under GPL v3.0 | Content Under CC BY 3.0
Website alextselegidis.com ·
GitHub alextselegidis ·
Twitter @alextselegidis