diff --git a/electron/components/file.js b/electron/components/file.js
index 8df05420d05b17f202ab73e94ec0538677fbd8a3..071e25116aa4dcec38dbc1dcd38d4dc09fa977ce 100644
--- a/electron/components/file.js
+++ b/electron/components/file.js
@@ -184,6 +184,13 @@ const writeProjectData = async function (workdir, data) {
     fs.writeFileSync(path.join(workdir, 'project.json'), data);
 };
 
+/**
+ * Write the epoc data to the content.json file in workdir
+ */
+const writeEpocData = async function (workdir, data) {
+    fs.writeFileSync(path.join(workdir, 'content.json'), data);
+};
+
 /**
  * Copy the imported file to the workdir
  * @param {string} workdir
@@ -238,6 +245,7 @@ module.exports = {
     saveAsEpocProject,
     exportProject,
     writeProjectData,
+    writeEpocData,
     readProjectData,
     copyFileToWorkdir,
     cleanAllWorkdir
diff --git a/electron/components/ipc.js b/electron/components/ipc.js
index ff03ff9e901e8214abe4a8de84d568185b2b76ea..a169d7614b7021b2f5fdeeac1be6b87f21d3b15b 100644
--- a/electron/components/ipc.js
+++ b/electron/components/ipc.js
@@ -2,7 +2,7 @@ const { ipcMain } = require('electron');
 const path = require('path');
 const store = require('./store');
 const { runPreview } = require('./preview');
-const { getRecentFiles, pickEpocProject, openEpocProject, newEpocProject, saveEpocProject, exportProject, writeProjectData, readProjectData, copyFileToWorkdir } = require('./file');
+const { getRecentFiles, pickEpocProject, openEpocProject, newEpocProject, saveEpocProject, exportProject, writeProjectData, writeEpocData, readProjectData, copyFileToWorkdir } = require('./file');
 
 /**
  * Setup ipc listeners that are received from renderer process
@@ -66,6 +66,10 @@ const setupIpcListener = function (targetWindow) {
         await writeProjectData(store.state.currentProject.workdir, data);
     });
 
+    ipcMain.on('writeEpocData', async (event, data) => {
+        await writeEpocData(store.state.currentProject.workdir, data);
+    });
+
     ipcMain.on('importFile', async (event, filepath) => {
         sendToFrontend(targetWindow, 'fileImported', await copyFileToWorkdir(store.state.currentProject.workdir, filepath));
     });
diff --git a/electron/electron.js b/electron/electron.js
index 842e200f21cce48b8e80e75a09629f1ba989467d..e8245e97027460f60c1fe53a96ded8e873511ad8 100644
--- a/electron/electron.js
+++ b/electron/electron.js
@@ -60,7 +60,7 @@ app.whenReady().then(() => {
     };
 
     session.defaultSession.webRequest.onBeforeRequest(filter, (details, callback) => {
-        if (details.url.indexOf('assets/') !== -1) {
+        if (mainWindow.webContents.id === details.webContents.id && details.url.indexOf('assets/') !== -1) {
             const filepath = details.url.split('assets/')[1];
 
             return callback({ redirectURL: `assets://assets/${filepath}` });
diff --git a/src/features/forms/FormPanel.vue b/src/features/forms/FormPanel.vue
index a7d5892aff8fc4d6f96a5fcf285c6b315439bd39..a90fce00842869809e261c1bcfca7f03ff95de1c 100644
--- a/src/features/forms/FormPanel.vue
+++ b/src/features/forms/FormPanel.vue
@@ -11,7 +11,7 @@ function actionOnForm(action: string) {
     switch (action) {
     case 'delete':
         editorStore.deleteElement(editorStore.openedNodeId);
-        projectService.saveProjectData();
+        projectService.writeProjectData();
         break;
     }
 }
diff --git a/src/features/forms/components/GenericField.vue b/src/features/forms/components/GenericField.vue
index 5dacb23161506b8e91877bc52acfc2a75453e95a..67f403166919bc8130df08f3270841ae7ce6e3c6 100644
--- a/src/features/forms/components/GenericField.vue
+++ b/src/features/forms/components/GenericField.vue
@@ -20,7 +20,7 @@ const node = editorStore.openedParentId ? findNode(editorStore.openedParentId) :
 
 function onInput(value, id) {
     node.data.formValues[id] = value;
-    projectService.saveProjectData();
+    projectService.writeProjectData();
 }
 
 function onRepeatInput(value, id) {
@@ -52,7 +52,7 @@ function onRepeatInput(value, id) {
             node.data.formValues[id][value.index][value.id] = value.value;
         }
     }
-    projectService.saveProjectData();
+    projectService.writeProjectData();
 }
 
 </script>
diff --git a/src/shared/classes/epoc-v1.ts b/src/shared/classes/epoc-v1.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dcdd623ab28496b3080f84618882891c5ac21ebe
--- /dev/null
+++ b/src/shared/classes/epoc-v1.ts
@@ -0,0 +1,64 @@
+import { Assessment, Chapter, Content, Epoc, html, Parameters, uid } from '@epoc/epoc-specs/dist/v1';
+import { Question } from '@epoc/epoc-specs/dist/v1/question';
+import { Author } from '@epoc/epoc-specs/dist/v1/author';
+
+export class EpocV1 implements Epoc {
+    id: string;
+    title: string;
+    image: string;
+    objectives: string[];
+    summary: html;
+    teaser: string;
+    thumbnail: string;
+    version: string;
+    certificateScore: number;
+    download: string;
+    lastModif: string;
+    chaptersCount: number;
+    assessmentsCount: number;
+    authors:Author[];
+    parameters: Parameters;
+    chapters: Record<uid, Chapter>;
+    contents: Record<uid, Content>;
+    questions: Record<uid, Question>;
+
+    constructor(
+        id: string, title: string, image: string, objectives: string[], summary: html, teaser: string,
+        thumbnail: string, version: string, certificateScore: number, authors: Author[],
+        chapterParameter: string
+    ) {
+        this.id = id;
+        this.title = title;
+        this.image = image;
+        this.objectives = objectives;
+        this.summary = summary;
+        this.teaser = teaser;
+        this.thumbnail = thumbnail;
+        this.version = version;
+        this.certificateScore = certificateScore;
+        this.authors = authors;
+        this.parameters = {
+            chapterParameter
+        };
+        this.chapters = {};
+        this.contents = {};
+        this.questions = {};
+        this.chaptersCount = 0;
+        this.assessmentsCount = 0;
+        this.download = '';
+    }
+
+    addChapter(id: uid, chapter: Chapter) {
+        this.chapters[id] = chapter;
+    }
+
+    addContent(id, chapterId, content) {
+        this.questions[id] = content;
+        this.chapters[chapterId].contents.push(id);
+    }
+
+    addDuestion(id, contentId, question) {
+        this.questions[id] = question;
+        (this.contents[contentId] as Assessment).questions.push(id);
+    }
+}
\ No newline at end of file
diff --git a/src/shared/data/form.data.ts b/src/shared/data/form.data.ts
index 14d76d7424898edb1dd17cc1c19bdba8f3b15cd2..b2989228797d7041ec8fc92035cf4d7b79375219 100644
--- a/src/shared/data/form.data.ts
+++ b/src/shared/data/form.data.ts
@@ -191,6 +191,68 @@ export const epocForm: Form = {
                 }
             ]
         },
+        {
+            name: 'Auteurs',
+            inputs: [
+                {
+                    id: 'authors',
+                    label: 'Auteur',
+                    type: 'repeat',
+                    value: '',
+                    inputs: [
+                        {
+                            id: 'name',
+                            type: 'text',
+                            label: 'Nom',
+                            placeholder: 'Préom nom',
+                            value: ''
+                        },
+                        {
+                            id: 'image',
+                            type: 'file',
+                            label: 'Image',
+                            placeholder: 'Ajouter une image',
+                            value: '',
+                            accept: '.png,.jpg,.jpeg,.gif,.bmp,.svg,.webp'
+                        },
+                        {
+                            id: 'title',
+                            type: 'text',
+                            label: 'Titre',
+                            placeholder: 'Chercheuse à l\'Inria',
+                            value: '',
+                        },
+                        {
+                            id: 'description',
+                            type: 'ql-editor',
+                            label: '',
+                            placeholder: 'Description',
+                            value: ''
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            name: 'Objectifs',
+            inputs: [
+                {
+                    id: 'objectives',
+                    label: 'Objectif',
+                    type: 'repeat',
+                    value: '',
+                    inputs: [
+                        {
+                            id: '',
+                            type: 'textarea',
+                            label: '',
+                            placeholder: 'Saisissez un objectif ...',
+                            value: ''
+                        }
+                    ]
+                }
+            ]
+        },
         {
             name: 'Paramètres :',
             inputs : [
diff --git a/src/shared/services/editor.service.ts b/src/shared/services/editor.service.ts
index 4ef4bc518ea3e8876d99fe78189d9fff23e9ecc4..cfe519bfdea73ffe037996018f3d420479ca00b3 100644
--- a/src/shared/services/editor.service.ts
+++ b/src/shared/services/editor.service.ts
@@ -2,7 +2,6 @@ import { ApiInterface } from '@/src/shared/interfaces/api.interface';
 import { router } from '@/src/router';
 import { useEditorStore, useProjectStore } from '@/src/shared/stores';
 import { ePocProject } from '@/src/shared/interfaces';
-import { projectService } from './project.service';
 import { createToaster } from '@meforma/vue-toaster';
 
 const toaster = createToaster({
@@ -139,7 +138,6 @@ function openEpocProject(project): void {
 function saveEpocProject(): void {
     editorStore.saving = true;
     api.send('saveEpocProject');
-    projectService.createContentJSON();
 }
 
 function runPreview(): void {
diff --git a/src/shared/services/project.service.ts b/src/shared/services/project.service.ts
index bf92b07daa7e24f5e83d202f4e149d0da7ae0f07..907c0f319c5745eb952c4fd467b73b1acd466dc4 100644
--- a/src/shared/services/project.service.ts
+++ b/src/shared/services/project.service.ts
@@ -1,16 +1,19 @@
 import { ApiInterface } from '@/src/shared/interfaces/api.interface';
 import { useProjectStore } from '../stores';
-import { getConnectedEdges, useVueFlow } from '@vue-flow/core';
+import { getConnectedEdges, GraphNode, useVueFlow } from '@vue-flow/core';
+import { EpocV1 } from '@/src/shared/classes/epoc-v1';
 
 declare const api: ApiInterface;
 
 const { toObject, onNodesChange, nodes, edges, findNode }  = useVueFlow({ id: 'main' });
 const projectStore = useProjectStore();
 
-function saveProjectData(): void {
+function writeProjectData(): void {
     debounceFunction(500, () => {
         const data = JSON.stringify(toObject());
+        const content = JSON.stringify(createContentJSON());
         api.send('writeProjectData', data);
+        api.send('writeEpocData', content);
     });
 }
 
@@ -32,116 +35,70 @@ const debounceFunction = function (delay, cb) {
 };
 
 onNodesChange(() => {
-    saveProjectData();
+    writeProjectData();
 });
 
 
-function createContentJSON() {
-    // const content = {};
-    // content['chapters'] = {};
-    // content['contents'] = {};
-    // const startingNode = nodes.value.filter((node) => { return node.type === 'epoc' || node.type === 'chapter';});
-    // startingNode.forEach((node) => {
-    //     if(node.type === 'epoc') {
-    //         const inputs = node.data.form.fields[0].inputs;
-    //         content['lastModif'] = new Date().toISOString();
-    //         content['title'] = inputs[0].value;
-    //         content['image']= inputs[2].value;
-    //         content['thumbnail'] = inputs[3].value;
-    //         content['teaser'] = inputs[4].value;
-    //         content['summary'] = inputs[5].value;
-    //         content['id'] = inputs[6].value;
-    //         content['edition'] = inputs[7].value;
-    //         content['parameters'] = {
-    //             'chapterParameters': inputs[1].value
-    //         };
-
-    //         //TODO
-    //         content['author'] = {};
-    //         content['certificateScore'] = 0;
-    //         content['plugins'] = [];
-    //     }
-    //     if(node.type === 'chapter') {
-    //         const chapter = {};
-    //         const titleInputs = node.data.form.fields[0].inputs;
-    //         chapter['title'] = titleInputs[0].value;
-    //         const objectiveInputs = node.data.form.fields[1].inputs;
-    //         const objectives = [];
-    //         for(const objective of objectiveInputs) {
-    //             objectives.push(objective.inputs[0].value);
-    //         }
-    //         chapter['objective'] = objectives;
-
-    //         chapter['contents'] = [];
-            
-    //         let nextEdge = getNextEdge(node);
-    //         while (nextEdge) {
-    //             const nextNode = findNode(nextEdge.target);
-    //             chapter['contents'].push(nextNode.data.contentId);
-                
-    //             const type = identifyTemplate(nextNode);
-    //             const element = {};
-    //             if(type === 'video') {
-    //                 const titleInput = nextNode.data.form.fields[0].inputs[0].value;
-    //                 const summaryInput = nextNode.data.elements[0].form.fields[0].inputs[1].value;
-                    
-    //                 element['type'] = 'video';
-    //                 element['title'] = titleInput;
-    //                 element['summary'] = summaryInput;
-                    
-    //                 //TODO
-    //                 element['source'] = '';
-    //                 element['subtitles'] = [];
-    //                 element['transcript'] = '';
-    //                 element['poster'] = '';
-                    
-    //             } else if(type === 'text') {
-    //                 const titleInput = nextNode.data.form.fields[0].inputs[0].value;
-    //                 const htmlInput = nextNode.data.elements[0].form.fields[0].inputs[0].value;
-
-    //                 element['type'] = 'html';
-    //                 element['title'] = titleInput;
-    //                 element['html'] = htmlInput;
-
-    //             } else {
-    //                 const question = {};
-    //                 const element = nextNode.data.elements[0];
-    //                 question['type'] = element.action.type;
-
-    //                 const fields = element.form.fields;
-
-    //                 question['score'] = fields[0].inputs[1].value;
-    //                 question['statement'] = fields[0].inputs[0].value;
-    //                 question['']
-
-    //                 console.log('question:',question);
-    //                 console.log('node:', nextNode);
-    //             }
-    //             content['contents'][nextNode.data.contentId] = element;
-                
-    //             nextEdge = getNextEdge(nextNode);
-    //         }
-    //         content['chapters'][node.data.contentId] = chapter;
-    //     }
-    // });
-    // console.log('content:', JSON.stringify(content));
+function createContentJSON() : EpocV1 {
+
+    const epocNode = nodes.value.find((node) => { return node.type === 'epoc'; });
+    const chapterNodes = nodes.value.filter((node) => { return node.type === 'chapter'; });
+
+    const ePocValues = epocNode.data.formValues;
+
+    const epoc = new EpocV1(
+        ePocValues.id || 'E000XX',
+        ePocValues.title || 'Title',
+        ePocValues.image || '',
+        ePocValues.objectives || [],
+        ePocValues.summary || '',
+        ePocValues.teaser || '',
+        ePocValues.thumbnail || '',
+        ePocValues.version || new Date().getFullYear(),
+        ePocValues.certificateScore || 0,
+        ePocValues.authors || {},
+        ePocValues.chapterParameter
+    );
+
+    console.log(epoc);
+
+    chapterNodes.forEach(chapter => {
+        console.log(chapter.data);
+        const chapterValues = chapter.data.formValues;
+        epoc.addChapter(chapter.data.contentId, {
+            title: chapterValues.title || '',
+            image: chapterValues.image || '',
+            objectives: chapterValues.objectives || [],
+            contents: []
+        });
+        let nextNode = getNextNode(chapter);
+        while (nextNode) {
+            console.log(nextNode.data);
+            const chapterValues = chapter.data.formValues;
+            epoc.addChapter(chapter.data.contentId, {
+                title: chapterValues.title || '',
+                image: chapterValues.image || '',
+                objectives: chapterValues.objectives || [],
+                contents: []
+            });
+            nextNode = getNextNode(nextNode);
+        }
+    });
+
+
+    return epoc;
 }
 
-function getNextEdge(node) {
+function getNextNode(node) {
     const edge = getConnectedEdges([node], edges.value).filter((edge) => edge.source === node.id)[0];
-    return edge ? { target: edge.target, source: edge.source } : null;
+    return edge ? getNodeById(edge.target) : null;
 }
 
-function identifyTemplate(node) {
-    if(node.data.type !== 'template'){
-        return null;
-    } else {
-        return node.data.elements[0].action.type;
-    }
+function getNodeById(id) : GraphNode {
+    return nodes.value.find((node) => { return node.id === id; });
 }
 
 export const projectService = {
     importFile,
-    saveProjectData,
-    createContentJSON,
+    writeProjectData
 };
\ No newline at end of file