diff --git a/packages/easy-sitemap/.eslintrc.js b/packages/easy-sitemap/.eslintrc.js
new file mode 100644
index 0000000..7a0472e
--- /dev/null
+++ b/packages/easy-sitemap/.eslintrc.js
@@ -0,0 +1,5 @@
+module.exports = {
+ "parserOptions": {
+ "project": __dirname + "/tsconfig.json"
+ }
+}
\ No newline at end of file
diff --git a/packages/easy-sitemap/.npmignore b/packages/easy-sitemap/.npmignore
new file mode 100644
index 0000000..b873d06
--- /dev/null
+++ b/packages/easy-sitemap/.npmignore
@@ -0,0 +1,13 @@
+node_modules
+src
+test
+.babelrc
+.eslintrc.js
+.gitignore
+.npmignore
+tsconfig.*
+webpack.config.js
+yarn-error.log
+coverage
+__tests__
+jest.config.js
diff --git a/packages/easy-sitemap/CHANGELOG.md b/packages/easy-sitemap/CHANGELOG.md
new file mode 100644
index 0000000..be60ed3
--- /dev/null
+++ b/packages/easy-sitemap/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]()
+
+## [1.0.0] - 2021-01-20
+
+### Added
+- The sitemap is ready !
+
+
+[1.0.4]: https://github.com/dzeiocom/libs/releases/tag/%40dzeio%2Fobject-util%401.0.4
+[1.0.2]: https://github.com/dzeiocom/libs/releases/tag/%40dzeio%2Fobject-util%401.0.2
+[1.0.1]: https://github.com/dzeiocom/libs/releases/tag/%40dzeio%2Fobject-util%401.0.1
+[1.0.0]: https://github.com/dzeiocom/libs/releases/tag/%40easy-sitemap%401.0.0
diff --git a/packages/easy-sitemap/README.md b/packages/easy-sitemap/README.md
new file mode 100644
index 0000000..3476f5f
--- /dev/null
+++ b/packages/easy-sitemap/README.md
@@ -0,0 +1,48 @@
+# URL Manager
+
+A very easy to use sitemap generator
+
+## Usage
+
+- Import easy-sitemap
+
+```typescript
+import Sitemap from 'easy-sitemap'
+// or
+const Sitemap = require('easy-sitemap').default
+```
+
+- Initialize it
+
+```typescript
+// Create a new instance
+const sitemap = new Sitemap('https://www.example.com') // initialize using your website base
+
+// if you want to let the library manage the response object the line is this
+const sitemap = new Sitemap('https://www.example.com', {
+ response: res
+})
+
+```
+
+- add you're paths
+
+```typescript
+sitemap.addEntry('/path')
+
+// you can also add optionnal elements
+sitemap.addEntry('/path', {
+ // each one are optionnal and they don't all need to be added
+ changefreq: 'always', // webpage change freq
+ lastmod: new Date('2021-01-20'), // webpage lastmod Date
+ priority: 1 // crawler priority
+})
+```
+
+- finally build it !
+
+```typescript
+// it will return a string containing the whole sitemap
+// if you are letting the library manage the response Object it will return an empty string but the page will render !
+const result = sitemap.build()
+```
diff --git a/packages/easy-sitemap/__tests__/__snapshots__/index.test.ts.snap b/packages/easy-sitemap/__tests__/__snapshots__/index.test.ts.snap
new file mode 100644
index 0000000..dbb1d4d
--- /dev/null
+++ b/packages/easy-sitemap/__tests__/__snapshots__/index.test.ts.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Basic Sitemap Tests should not add changefreq if value is incorrect 1`] = `"https://www.example.com/path"`;
+
+exports[`Basic Sitemap Tests should not add priority when it is incorrect 1`] = `"https://www.example.com/path"`;
+
+exports[`Basic Sitemap Tests should return a basic sitemap 1`] = `"https://www.example.com/pathhttps://www.example.com/"`;
+
+exports[`Basic Sitemap Tests should return a sitemap 1`] = `"https://www.example.com/pathalways2021-01-20T00:00:00.000Z1https://www.example.com/"`;
+
+exports[`Basic Sitemap Tests should return an empty sitemap 1`] = `""`;
diff --git a/packages/easy-sitemap/__tests__/index.test.ts b/packages/easy-sitemap/__tests__/index.test.ts
new file mode 100644
index 0000000..cc62d56
--- /dev/null
+++ b/packages/easy-sitemap/__tests__/index.test.ts
@@ -0,0 +1,43 @@
+///
+
+import Sitemap from '../src/Sitemap'
+
+describe('Basic Sitemap Tests', () => {
+ it('should return an empty sitemap', () => {
+ const sitemap = new Sitemap('https://www.example.com')
+ expect(sitemap.build()).toMatchSnapshot()
+ })
+ it('should return a basic sitemap', () => {
+ const sitemap = new Sitemap('https://www.example.com')
+ sitemap.addEntry('/path')
+ sitemap.addEntry('/')
+ expect(sitemap.build()).toMatchSnapshot()
+ })
+ it('should return a sitemap', () => {
+ const sitemap = new Sitemap('https://www.example.com')
+ sitemap.addEntry('/path', {
+ changefreq: 'always',
+ lastmod: new Date('2021-01-20'),
+ priority: 1
+ })
+ sitemap.addEntry('/')
+ expect(sitemap.build()).toMatchSnapshot()
+ })
+ it('should not add priority when it is incorrect', () => {
+ const sitemap = new Sitemap('https://www.example.com')
+ sitemap.addEntry('/path', {
+ // @ts-expect-error
+ priority: 255
+ })
+ expect(sitemap.build()).toMatchSnapshot()
+ })
+ it('should not add changefreq if value is incorrect', () => {
+ const sitemap = new Sitemap('https://www.example.com')
+ sitemap.addEntry('/path', {
+ // @ts-expect-error
+ changefreq: 'pouet'
+ })
+ expect(sitemap.build()).toMatchSnapshot()
+ })
+
+})
diff --git a/packages/easy-sitemap/jest.config.js b/packages/easy-sitemap/jest.config.js
new file mode 100644
index 0000000..b5ab11f
--- /dev/null
+++ b/packages/easy-sitemap/jest.config.js
@@ -0,0 +1 @@
+module.exports = require('../../jest.base.json')
diff --git a/packages/easy-sitemap/package.json b/packages/easy-sitemap/package.json
new file mode 100644
index 0000000..1e3bf78
--- /dev/null
+++ b/packages/easy-sitemap/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "easy-sitemap",
+ "version": "1.0.0",
+ "description": "A very easy sitemap maker library",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/dzeiocom/libs.git",
+ "directory": "packages/easy-sitemap"
+ },
+ "author": "Aviortheking",
+ "license": "MIT",
+ "main": "./dist/Sitemap.js",
+ "types": "./dist/Sitemap.d.ts",
+ "devDependencies": {
+ "@types/chai": "^4.2.12",
+ "@types/jest": "^26.0.10",
+ "jest": "^26.4.2",
+ "ts-node": "^9.0.0",
+ "typescript": "^4.0.2"
+ },
+ "scripts": {
+ "prepublishOnly": "yarn build",
+ "build": "tsc",
+ "test": "jest --coverage"
+ },
+ "keywords": [
+ "sitemap",
+ "sitemap.xml"
+ ]
+}
diff --git a/packages/easy-sitemap/src/Sitemap.ts b/packages/easy-sitemap/src/Sitemap.ts
new file mode 100644
index 0000000..5cfc9fc
--- /dev/null
+++ b/packages/easy-sitemap/src/Sitemap.ts
@@ -0,0 +1,70 @@
+import { ServerResponse } from 'http'
+
+export default class Sitemap {
+
+ private static allowedChangefreq = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never']
+
+ private datas = ''
+
+ public constructor(
+ private domain: string, private options?: {
+ response?: ServerResponse
+ }
+ ) {
+ if (this.options?.response) {
+ this.options.response.setHeader('Content-Type', 'text/xml')
+ this.options.response.write(this.datas)
+ }
+ }
+
+ public addEntry(path: string, options?: {
+ changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'
+ lastmod?: Date
+ priority?: 1 | 0.9 | 0.8 | 0.7 | 0.6 | 0.5 | 0.4 | 0.3 | 0.2 | 0.1 | 0
+ }) {
+ let entryString = ''
+
+ const url = `${this.domain}${path}`
+ .replace(/&/g, '&')
+ .replace(/'/g, ''')
+ .replace(/"/g, '"')
+ .replace(/>/g, '>')
+ .replace(/${url}`
+ if (options) {
+ if (options.changefreq) {
+ if (!Sitemap.allowedChangefreq.includes(options.changefreq)) {
+ console.warn(`changefreq is not one of the allowed words (${options.changefreq})\nChangeFreq won't be added`)
+ } else {
+ entryString += `${options.changefreq}`
+ }
+ }
+ if (options.lastmod) {
+ entryString += `${options.lastmod.toISOString()}`
+ }
+ if (options.priority) {
+ if (options.priority <= 1 && options.priority >= 0 && options.priority.toString().length <= 3) {
+ entryString += `${options.priority}`
+ } else {
+ console.warn(`Priority is not between 0 and 1 and only containing one decimal (${options.priority})\nPriority won't be added`)
+ }
+ }
+ }
+ entryString += ''
+ if (this.options?.response) {
+ this.options.response.write(entryString)
+ } else {
+ this.datas += entryString
+ }
+ }
+
+ public build(): string {
+ if (this.options?.response) {
+ this.options.response.write('')
+ this.options.response.end()
+ return ''
+ }
+ return this.datas + ''
+ }
+}
diff --git a/packages/easy-sitemap/tsconfig.json b/packages/easy-sitemap/tsconfig.json
new file mode 100644
index 0000000..c32b060
--- /dev/null
+++ b/packages/easy-sitemap/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "dist"
+ },
+ "files": [
+ "src/Sitemap.ts"
+ ]
+}