diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000000000000000000000000000000000..c394f5014f27a47bd99ee010987ad626ae7e31c8
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+# WordPress Coding Standards
+# https://make.wordpress.org/core/handbook/coding-standards/
+
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.yml]
+indent_style = space
+indent_size = 2
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..6b71fc789360605b77f8f82161887ac88953f392
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,12 @@
+.git/ export-ignore
+tests/ export-ignore
+vendor/ export-ignore
+.editorconfig export-ignore
+.gitattributes export-ignore
+.gitignore export-ignore
+.gitlab-ci.yml export-ignore
+.idea export-ignore
+apigen.neon export-ignore
+phpcs.xml.dist export-ignore
+phpunit-integration.xml export-ignore
+phpunit-unit.xml export-ignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cee7481eca58aa992f160301db54ebcaf6c7e928
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/vendor/
+.idea
+node_modules
+composer.lock
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d1a592d64911994b16f72f08d2b587a74ef2c37b
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,8 @@
+variables:
+  DISABLE_CODECEPTION: 1
+  DISABLE_INTEGRATION_TESTS: 1
+  DISABLE_PHP_5_5: 1
+  IS_LIBRARY: 1
+
+include: 'https://gitlab.com/wpdesk/gitlab-ci/raw/master/gitlab-ci-1.2.yml'
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..963197d54b41886aab3393497ffd17a0ae8787d1
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+## [1.0.0] - 2023-03-06
+### Added
+- init
diff --git a/apigen.neon b/apigen.neon
new file mode 100644
index 0000000000000000000000000000000000000000..1aec8cf79a0fc4b0035465c5e90d65b85b3449e7
--- /dev/null
+++ b/apigen.neon
@@ -0,0 +1,27 @@
+destination: docs
+templateConfig: /app/theme-woocommerce/config.neon
+extensions: [php]
+source:
+    - src
+exclude:
+    - vendor
+    - tests
+    - languages
+
+charset: [UTF-8]
+main: Wordpress plugin
+title: Plugin template more info
+baseUrl: "/"
+
+templateTheme: default
+php: false
+sourceCode: false
+tree: true
+deprecated: false
+todo: false
+download: false
+
+accessLevels:       
+    - public
+    - private
+    - protected
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..f6cfaded48c8cba7cec452d4467d01fbe81f0004
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,68 @@
+{
+    "name": "wpdesk/wp-coupons-core",
+    "description": "Coupons library",
+    "license": "MIT",
+    "keywords": [
+        "wordpress",
+        "woocommerce",
+        "woocommerce-coupons",
+        "pdf",
+        "pdf builder"
+    ],
+    "homepage": "https://gitlab.com/wpdesk/wp-canva-editor",
+    "minimum-stability": "stable",
+    "authors": [
+        {
+            "name": "piotr.potrebka",
+            "email": "piotr.potrebka@wpdesk.net"
+        }
+    ],
+    "config": {
+        "sort-packages": true,
+        "platform": {
+            "php": "7.3"
+        },
+        "allow-plugins": {
+            "dealerdirect/phpcodesniffer-composer-installer": true,
+            "cweagans/composer-patches": true,
+            "wpdesk/wp-wpdesk-composer": true
+        }
+    },
+    "require": {
+        "php": ">=7.3",
+        "psr/log": "^1.1.0",
+        "wpdesk/wp-persistence": "^3.0",
+        "wpdesk/wp-view": "^2.0",
+        "wpdesk/wp-notice": "^3.1.1",
+        "wpdesk/wp-builder": "^2.0",
+        "pelago/emogrifier": "7.0",
+        "ext-json": "*"
+    },
+    "require-dev": {
+        "10up/wp_mock": "*",
+        "mockery/mockery": "*",
+        "phpunit/phpunit": "<7",
+        "wp-coding-standards/wpcs": "^2.3.0",
+        "squizlabs/php_codesniffer": "^3.0.2"
+    },
+    "autoload": {
+        "psr-4": {
+            "WPDesk\\Library\\WPCoupons\\": "src/Coupons"
+        }
+    },
+    "autoload-dev": {},
+    "extra": {
+        "text-domain": "wp-coupons-core",
+        "translations-folder": "lang",
+        "po-files": {
+            "pl_PL": "pl_PL.po"
+        }
+    },
+    "scripts": {
+        "phpcs": "phpcs",
+        "phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
+        "phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
+        "phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
+        "phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
+    }
+}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000000000000000000000000000000000000..b736f2578f2af84a07fbedde80459660d1565408
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<ruleset name="WordPress Coding Standards for WP Desk Plugin">
+	<description>Sniffs for WordPress WPDesk plugins</description>
+
+	<config name="installed_paths" value="vendor/wp-coding-standards/wpcs,vendor/wimg/php-compatibility" />
+
+    <rule ref="PHPCompatibility"/>
+	<config name="testVersion" value="5.5-"/>
+
+	<rule ref="WordPress"/>
+
+	<config name="text_domain" value="wpdesk-plugin,default,s214-settings-demo"/>
+
+	<arg name="extensions" value="php"/>
+
+	<file>./classes</file>
+	<exclude-pattern>*/settings-api/*</exclude-pattern>
+</ruleset>
diff --git a/phpunit-integration.xml b/phpunit-integration.xml
new file mode 100644
index 0000000000000000000000000000000000000000..634b884c1c32948885c7e1ff159b3531e235d298
--- /dev/null
+++ b/phpunit-integration.xml
@@ -0,0 +1,34 @@
+<phpunit bootstrap="tests/integration/bootstrap.php"
+         backupGlobals="false"
+>
+    <testsuites>
+        <testsuite>
+            <directory prefix="Test" suffix=".php">./tests/integration</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory suffix=".php">src</directory>
+            <exclude>
+                <file>src/init.php</file>
+                <directory>src/assets</directory>
+                <directory suffix=".php">tests</directory>
+                <directory suffix=".php">vendor</directory>
+            </exclude>
+        </whitelist>
+    </filter>
+
+    <logging>
+        <log type="junit" target="build-coverage/report.junit.xml"/>
+        <log type="coverage-html" target="build-coverage/coverage" charset="UTF-8" yui="true" highlight="true"/>
+        <log type="coverage-text" target="build-coverage/coverage.txt"/>
+        <log type="coverage-clover" target="build-coverage/clover.xml"/>
+    </logging>
+
+    <php>
+        <env name="WP_DEVELOP_DIR" value="/tmp/wordpress-develop"/>
+        <env name="WC_DEVELOP_DIR" value="/tmp/woocommerce"/>
+    </php>
+
+</phpunit>
diff --git a/phpunit-unit.xml b/phpunit-unit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f3b7ead97601294e87575236952d21711e0cec07
--- /dev/null
+++ b/phpunit-unit.xml
@@ -0,0 +1,21 @@
+<phpunit bootstrap="tests/unit/bootstrap.php">
+    <testsuites>
+        <testsuite>
+            <directory prefix="Test_" suffix=".php">./tests/unit/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory suffix=".php">src</directory>
+        </whitelist>
+    </filter>
+
+    <logging>
+        <log type="junit" target="build-coverage/report.junit.xml"/>
+        <log type="coverage-html" target="build-coverage/coverage" charset="UTF-8" yui="true" highlight="true"/>
+        <log type="coverage-text" target="build-coverage/coverage.txt"/>
+        <log type="coverage-clover" target="build-coverage/clover.xml"/>
+    </logging>
+
+</phpunit>
diff --git a/src/Abstracts/EmailAbstract.php b/src/Abstracts/EmailAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..0085b6863b4f947ec847aeff28ae50a7857a4844
--- /dev/null
+++ b/src/Abstracts/EmailAbstract.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace WPDesk\Library\WPEmail\Abstracts;
+
+abstract class EmailAbstract implements EmailInterface {
+
+    /**
+     * Define unique email ID.
+     *
+     * @return string
+     */
+    abstract public function get_id(): string;
+
+    /**
+     * Get defined placeholders.
+     *
+     * @return array
+     */
+    public function get_placeholders(): array {
+
+    }
+
+    /**
+     * Get email subject.
+     *
+     * @return string
+     */
+    public function get_subject(): string {
+
+    }
+
+    /**
+     * Get email heading.
+     *
+     * @return string
+     */
+    public function get_heading(): string {
+
+    }
+
+    /**
+     * Get valid recipients.
+     *
+     * @return array
+     */
+    public function get_recipients(): array {
+
+    }
+
+    /**
+     * Get email headers.
+     *
+     * @return string
+     */
+    public function get_headers(): string {
+
+    }
+
+    /**
+     * Get email attachments.
+     *
+     * @return array
+     */
+    public function get_attachments(): array {
+
+    }
+
+    /**
+     * Get email type.
+     *
+     * @return string
+     */
+    public function get_type(): string {
+
+    }
+
+    /**
+     * Get email content.
+     *
+     * @return string
+     */
+    public function get_content(): string {
+
+    }
+
+    /**
+     * Send email.
+     *
+     * @return void
+     */
+    public function send(): void {
+        wp_mail(
+            $this->get_recipients(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments()
+        );
+    }
+
+}
diff --git a/src/Abstracts/EmailInterface.php b/src/Abstracts/EmailInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..aff140ee8c072959b964719f7bb4a33e06c0df5a
--- /dev/null
+++ b/src/Abstracts/EmailInterface.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace WPDesk\Library\WPEmail\Abstracts;
+
+interface EmailInterface {
+
+    /**
+     * Define unique email ID.
+     *
+     * @return string
+     */
+    public function get_id(): string;
+
+    /**
+     * Get defined placeholders.
+     *
+     * @return array
+     */
+    public function get_placeholders(): array;
+
+    /**
+     * Get email subject.
+     *
+     * @return string
+     */
+    public function get_subject(): string;
+
+    /**
+     * Get email heading.
+     *
+     * @return string
+     */
+    public function get_heading(): string;
+
+    /**
+     * Get valid recipients.
+     *
+     * @return array
+     */
+    public function get_recipients(): array;
+
+    /**
+     * Get email headers.
+     *
+     * @return string
+     */
+    public function get_headers(): string;
+
+    /**
+     * Get email attachments.
+     *
+     * @return array
+     */
+    public function get_attachments(): array;
+
+    /**
+     * Get email type.
+     *
+     * @return string
+     */
+    public function get_type(): string;
+
+    /**
+     * Get email content.
+     *
+     * @return string
+     */
+    public function get_content(): string;
+
+    /**
+     * Send email.
+     *
+     * @return void
+     */
+    public function send(): void;
+
+}
diff --git a/src/AdminEmail.php b/src/AdminEmail.php
new file mode 100644
index 0000000000000000000000000000000000000000..420b8b3eca970cf91c02cbaa98180cac5a07d1f4
--- /dev/null
+++ b/src/AdminEmail.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace WPDesk\Library\WPEmail;
+
+use WPDesk\Library\WPEmail\Abstracts\EmailAbstract;
+
+class AdminEmail extends EmailAbstract {
+
+    const ID = 'admin_email';
+
+    /**
+     * Define unique email ID.
+     *
+     * @return string
+     */
+    public function get_id(): string {
+        return self::ID;
+    }
+
+}
diff --git a/src/CustomerEmail.php b/src/CustomerEmail.php
new file mode 100644
index 0000000000000000000000000000000000000000..44eff7467e1508b42615e8e88ba28c58f41c417e
--- /dev/null
+++ b/src/CustomerEmail.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace WPDesk\Library\WPEmail;
+
+use WPDesk\Library\WPEmail\Abstracts\EmailAbstract;
+
+class CustomerEmail extends EmailAbstract {
+
+    const ID = 'customer_email';
+
+    /**
+     * Define unique email ID.
+     *
+     * @return string
+     */
+    public function get_id(): string {
+        return self::ID;
+    }
+
+}
diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php
new file mode 100644
index 0000000000000000000000000000000000000000..a422fd9c7fea652a15b2aced0b2e6134a5590201
--- /dev/null
+++ b/tests/integration/bootstrap.php
@@ -0,0 +1,28 @@
+<?php
+
+ini_set('error_reporting', E_ALL); // or error_reporting(E_ALL);
+ini_set('display_errors', '1');
+ini_set('display_startup_errors', '1');
+
+require_once __DIR__ . '/../../vendor/autoload.php';
+
+// disable xdebug backtrace
+if ( function_exists( 'xdebug_disable' ) ) {
+	xdebug_disable();
+}
+
+if ( getenv( 'PLUGIN_PATH' ) !== false ) {
+	define( 'PLUGIN_PATH', getenv( 'PLUGIN_PATH' ) );
+} else {
+	define( 'PLUGIN_PATH', __DIR__ . DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR );
+}
+
+require_once( getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit/includes/functions.php' );
+
+tests_add_filter( 'muplugins_loaded', function () {
+}, 100 );
+
+putenv('WP_TESTS_DIR=' . getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit');
+require_once( getenv( 'WC_DEVELOP_DIR' ) . '/tests/bootstrap.php' );
+
+do_action('plugins_loaded');
\ No newline at end of file
diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php
new file mode 100644
index 0000000000000000000000000000000000000000..76b8109582ae17560b77a6e0499b232e09047810
--- /dev/null
+++ b/tests/unit/bootstrap.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * PHPUnit bootstrap file
+ */
+
+require_once __DIR__ . '/../../vendor/autoload.php';
+
+WP_Mock::setUsePatchwork( true );
+WP_Mock::bootstrap();