{"pageProps":{"locale":{"code":"en","domain":"frenchstack.com","lang":"en-US","json":{"TRANSLATE":"Translate into","EN":"English","FR":"French","NO_TRANSLATION_AVAILABLE":"No translation available","PROFILE_OF":"Profile of","FILTER_BY_TAG":"Filter by tag","REMOVE_FILTER":"Remove filter","RESULT":"Result","RESULTS":"Results","FORM_CONTACT_SUPPORT":"Support","FORM_CONTACT_SALES":"Sales","FORM_CONTACT_BUGS":"Report a bug","FORM_LOADING":"Loading","FORM_SEND":"Send","FORM_VERIFY":"Verify","FORM_NAME":"Name","FORM_TOPIC":"Subject","FORM_PHONE":"Phone","FORM_EMAIL":"Email","FORM_MESSAGE":"Message","FORM_DOMAIN_PLACEHOLDER":"example.com","FORM_DOMAIN_AVAILABLE":"Congrats, <span data-selector='domain'></span> is available!","FORM_DOMAIN_TAKEN":"Sorry, <span data-selector='domain'></span> is taken.","SUBSCRIBE":"Subscribe","SUCCESS_CONTACT":"Your message has been successfully sent! We'll be in touch soon.","SOMETING_WENT_WRONG":"Oops, something went wrong. Please try again later.","PERFORMANCE":"Performance","ACCESSIBILITY":"Accessibility","BEST_PRACTICES":"Best Practices","SEO":"SEO","MOBILE":"Mobile","TABLET":"Tablet","DESKTOP":"Desktop","VISITORS":"Visitors","ENGAGEMENT":"Engagement","CONVERSIONS":"Conversions","JAN":"Jan","FEB":"Feb","MAR":"Mar","APR":"Apr","MAY":"May","JUN":"Jun","JUL":"Jul","AUG":"Aug","SEP":"Sep","OCT":"Oct","NOV":"Nov","DEC":"Dec","METHOD_PHONE":"Phone","METHOD_EMAIL":"Email","FOOTER_TAGLINE":"We create unique digital experiences for brands and businesses.","LOOP_ACTOR_AGENT":"AI agent","LOOP_STEPS":"Steps","LOOP_REPEATED":"repeated","AND":"and"},"subdomains":{"blog":"blog","clients":"clients","videos":"videos","services":"services"},"ogSection":"Technology"},"slugs":["en","blog"],"component":"paging","articles":[{"id":"content/articles/en/fallow-codebase-intelligence-typescript.mdx","heroSection":{"heroTitle":"Fallow measures, AI builds","heroSubtitle":"The duo that makes the ultimate software architect","heroBadge":"","heroColoredWords":"1,3","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"On one side, a locked-down, measurable architecture. On the other, an agent that executes tirelessly."}]},{"type":"p","children":[{"type":"text","text":"Together, they split, name and organize every line of code."}]}]},"heroSubtitleIsInline":false,"heroHasBackground":false,"heroImage":"/images/fallow-codebase-intelligence-typescript.png","heroVideoBackground":"","heroStyle":{"heroBg":"","heroMaxWidth":"","heroMs":"","heroTitleMb":"","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"","navbarBorderColor":"","navbarLinkActive":"","navbarLinkHover":""},"imageAlt":"fallow codebase intelligence typescript","imageWidth":1376,"imageHeight":768},"seoSection":{"metaTitle":"Fallow and AI agents: a hands-on take on code quality","metaDescription":"Hands-on feedback: Fallow, a TypeScript static analyzer written in Rust, acts as the source of truth for my AI agents and guides them to split functions and files into clear, well-named, well-organized units.","metaTags":"Fallow, TypeScript, AI agent, code quality, cognitive complexity, refactoring, Claude Code, Codex, static analysis, MCP, vibe coding","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2026-10-18T13:38:48.000Z","localeCode":"en","slug":"fallow-codebase-intelligence-typescript","url":"/en/blog/fallow-codebase-intelligence-typescript","ogId":"fallow-codebase-intelligence-typescript-blog-en","ogImagePath":"/og/fallow-codebase-intelligence-typescript-blog-en.png","type":"Article","title":"Fallow: code quality at the pace of AI agents","subtitle":"Hands-on feedback on a deterministic check for TypeScript","browserUrl":"","textPreview":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Fallow measures the complexity, dead code and duplication of a TypeScript project. Plugged into my AI agents, it turns every commit into a chance to split functions and files into well-named, well-organized units."}]}]},"subdomainKey":"blog","subdomain":"blog","draft":false,"logoAlt":"","logoWidth":0,"logoHeight":0,"icon":"code","body":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"AI agents now write a large share of the code in my projects. They deliver fast and well, with a constant tendency to "},{"type":"text","text":"extend what already exists","bold":true},{"type":"text","text":" rather than create a new concept. Request after request, a 20-line function grows to 100, a 100-line file grows to 500, and names only describe part of what they contain."}]},{"type":"p","children":[{"type":"text","text":"Fallow","bold":true},{"type":"text","text":" corrects this drift with remarkable efficiency. Before each commit, my agent runs Fallow to measure the project's functions and files. Until the verdict is green, it keeps splitting. This procedure guarantees code made of small functions, organized in single-responsibility files, whose names say exactly what they do."}]},{"type":"mdxJsxFlowElement","name":"codeTidy","children":[{"type":"text","text":""}],"props":{"before":"One file that does everything","after":"One responsibility per file","caption":"Fallow measures, the agent splits and puts each responsibility in its place."}},{"type":"hr","children":[{"type":"text","text":""}]},{"type":"h2","children":[{"type":"text","text":"Fallow in a nutshell"}]},{"type":"p","children":[{"type":"a","url":"https://fallow.tools","title":"Fallow - Codebase intelligence","children":[{"type":"text","text":"Fallow"}]},{"type":"text","text":" is an "},{"type":"text","text":"open source","italic":true},{"type":"text","text":" static analyzer for "},{"type":"text","text":"TypeScript and JavaScript","bold":true},{"type":"text","text":", released under the MIT license as a single Rust binary. It builds a complete graph of the repository (modules, exports, dependencies, functions) and derives four families of analyses from it:"}]},{"type":"ul","children":[{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Complexity","bold":true},{"type":"text","text":": Cyclomatic and cognitive complexity of every function, maintainability score of every file and a project health score out of 100."}]}]},{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Dead code","bold":true},{"type":"text","text":": Detection of files, exports, types and dependencies that nothing uses anymore."}]}]},{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Duplication","bold":true},{"type":"text","text":": Spotting blocks copied from one file to another, in TypeScript and JavaScript code as well as in stylesheets and UI components."}]}]},{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Architecture","bold":true},{"type":"text","text":": Enforcement of import boundaries (UI, business logic, data) and detection of circular dependencies."}]}]}]},{"type":"p","children":[{"type":"text","text":"The analyzer embeds "},{"type":"text","text":"no language model","bold":true},{"type":"text","text":": the same input always produces the same result. It runs on its own, without the TypeScript compiler or a Node.js runtime. According to the benchmarks published by the project, it can analyze a repository as large as the Next.js monorepo ("},{"type":"text","text":"20,558 files","bold":true},{"type":"text","text":") in under "},{"type":"text","text":"3 seconds","bold":true},{"type":"text","text":"."}]},{"type":"p","children":[{"type":"text","text":"This determinism makes it the right partner for an AI agent: the agent proposes, Fallow measures."}]},{"type":"mdxJsxFlowElement","name":"sourceNote","children":[{"type":"text","text":""}],"props":{"content":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Sources: the project's "},{"type":"a","url":"https://github.com/fallow-rs/fallow/blob/main/BENCHMARKS.md","title":null,"children":[{"type":"text","text":"BENCHMARKS.md"}]},{"type":"text","text":" (June 2026 measurements) and "},{"type":"a","url":"https://fallow.tools","title":null,"children":[{"type":"text","text":"fallow.tools"}]},{"type":"text","text":", accessed in October 2026."}]}]}}},{"type":"hr","children":[{"type":"text","text":""}]},{"type":"h2","children":[{"type":"text","text":"A referee in the agent loop"}]},{"type":"p","children":[{"type":"text","text":"At the pace agents work, I no longer review every line one by one. Asking an agent to “write simple code” does not ensure that the constraint is met."}]},{"type":"p","children":[{"type":"text","text":"Fallow becomes the safeguard of every commit. The diagram below shows the loop the agent follows for each task:"}]},{"type":"mdxJsxFlowElement","name":"agentLoop","children":[{"type":"text","text":""}],"props":{"steps":[{"actor":"agent","title":"Development","detail":"Implementation of the request, with no particular constraint"},{"actor":"fallow","title":"Measurement","detail":"Flags overly complex functions, files to split, unused exports and duplicated blocks","inLoop":true},{"actor":"agent","title":"Splitting","detail":"Extraction of steps into named functions and of responsibilities into dedicated files","inLoop":true},{"actor":"git","title":"Commit","detail":"Accepted only on a “pass” verdict"}],"loopLabel":"until green","caption":"The lock blocks the commit as long as Fallow returns a “fail” verdict."}},{"type":"p","children":[{"type":"text","text":"Splitting happens at two scales:"}]},{"type":"ul","children":[{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Function","bold":true},{"type":"text","text":": Default thresholds of "},{"type":"text","text":"20","bold":true},{"type":"text","text":" for cyclomatic complexity, "},{"type":"text","text":"15","bold":true},{"type":"text","text":" for cognitive complexity and "},{"type":"text","text":"60 lines","bold":true},{"type":"text","text":" per function, which I keep as they are."}]}]},{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"File","bold":true},{"type":"text","text":": Maintainability score computed from size, complexity density, dead code and dependencies, along with prioritized recommendations such as “split a file that too many others depend on” or “extract the "},{"type":"text","text":"parseRow","code":true},{"type":"text","text":" function from a 520-line file”."}]}]}]},{"type":"p","children":[{"type":"text","text":"Fallow does not say how to fix things: it points out what is too long, too nested, too central or repeated, and leaves it to the agent to "},{"type":"text","text":"split and organize","bold":true},{"type":"text","text":"."}]},{"type":"mdxJsxFlowElement","name":"sourceNote","children":[{"type":"text","text":""}],"props":{"content":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Source: "},{"type":"a","url":"https://fallow.tools/docs/explanations/health/","title":null,"children":[{"type":"text","text":"Health explained"}]},{"type":"text","text":", Fallow documentation accessed in October 2026."}]}]}}},{"type":"hr","children":[{"type":"text","text":""}]},{"type":"h2","children":[{"type":"text","text":"Hands-on feedback"}]},{"type":"p","children":[{"type":"text","text":"I coded a small "},{"type":"text","text":"TypeScript","bold":true},{"type":"text","text":" bot that automatically books my fitness classes, whose spots fill up within minutes. Once it was stable, I handed the project to an AI agent to integrate it into "},{"type":"text","text":"Home Assistant","bold":true},{"type":"text","text":", with a graphical interface, controllable bookings and phone notifications."}]},{"type":"p","children":[{"type":"img","url":"/images/fallow-rpm-lesmills-bot.png","alt":"Fitness class booking bot interface in Home Assistant","caption":"1448x836","children":[{"type":"text","text":""}]}]},{"type":"p","children":[{"type":"text","text":"The agent quickly delivered a working project, but every change had been grafted onto the existing code. A single function handled the API login, fetching the schedule, picking the time slot and then booking, and the whole interface lived in a single file."}]},{"type":"p","children":[{"type":"text","text":"Once Fallow was plugged in, the agent isolated each "},{"type":"text","text":"business step","bold":true},{"type":"text","text":" in a dedicated function, with a name that says what it does. It then applied "},{"type":"text","text":"the same responsibility-based split","bold":true},{"type":"text","text":" at the file level."}]},{"type":"p","children":[{"type":"text","text":"The result shows across three parts of the project:"}]},{"type":"ul","children":[{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Booking","bold":true},{"type":"text","text":": The main function goes from "},{"type":"text","text":"88 to 28 lines","bold":true},{"type":"text","text":" and delegates login, schedule, slot selection and booking to "},{"type":"text","text":"4 functions","bold":true},{"type":"text","text":" named after their step."}]}]},{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Interface","bold":true},{"type":"text","text":": The "},{"type":"text","text":"App.tsx","code":true},{"type":"text","text":" file goes from "},{"type":"text","text":"501 to 116 lines","bold":true},{"type":"text","text":", spread across "},{"type":"text","text":"7 reusable components","bold":true},{"type":"text","text":", a shared types file and a dedicated "},{"type":"text","text":"hook","italic":true},{"type":"text","text":"."}]}]},{"type":"li","children":[{"type":"lic","children":[{"type":"text","text":"Notifications","bold":true},{"type":"text","text":": Notification sending, written "},{"type":"text","text":"3 times","bold":true},{"type":"text","text":", now lives in a single place under the name "},{"type":"text","text":"notifyBookingSuccess","code":true},{"type":"text","text":"."}]}]}]},{"type":"hr","children":[{"type":"text","text":""}]},{"type":"h2","children":[{"type":"text","text":"A source of truth to keep the agent on track"}]},{"type":"p","children":[{"type":"text","text":"An AI agent works on a project the way a developer would. It looks for the right file, reads what surrounds it and changes what it understands. A project generated prompt after prompt, never refactored, picks up the traits of "},{"type":"text","text":"spaghetti","italic":true},{"type":"text","text":" code from the very first requests: files with mixed responsibilities, approximate names, duplicated logic. In that context, finding the right file forces the agent to read more, and changing what it understands is no longer enough, because side effects multiply."}]},{"type":"p","children":[{"type":"text","text":"Fallow reverses this slope without requiring software architecture expertise. Splitting, naming and organizing rules are measured and the verdict is binding on the agent, without having to spell them out in every prompt or check them during review. The benefit shows on three levels:"}]},{"type":"mdxJsxFlowElement","name":"benefitCards","children":[{"type":"text","text":""}],"props":{"items":[{"icon":"shield","tone":"success","title":"Fewer regressions","text":"Short functions and single-responsibility files, where every change stays confined to the part concerned."},{"icon":"coins","tone":"warning","title":"Fewer tokens","text":"Navigation guided by explicit names, without rereading entire files to find the right line."},{"icon":"target","tone":"primary","title":"More control","text":"An objective, reproducible criterion to validate the agent's work, where a natural-language instruction remains unverifiable."}]}},{"type":"p","children":[{"type":"text","text":"Hand Fallow to your agent. On every commit, it splits, names and organizes the code without you having to dictate each rule. You keep a readable project that costs less to evolve, and every new request starts from a healthy base. Quality is no longer decreed, it is verified."}]},{"type":"mdxJsxFlowElement","name":"buttons","children":[{"type":"text","text":""}],"props":{"buttons":[{"icon":"gitHub","label":"Fallow on GitHub","link":"https://github.com/fallow-rs/fallow","style":"primary"},{"icon":"codeFile","label":"Documentation","link":"https://fallow.tools/docs","style":"light"}]}}]},"dateCreate":"2026-10-18T09:00:00.000Z","dateUpdate":"2026-10-18T09:00:00.000Z","author":{"id":"content/authors/en/nicolas-roehm-bettcher.mdx","heroSection":{"heroTitle":"Nicolas Roehm","heroSubtitle":"Software Engineer","heroBadge":"","heroColoredWords":"","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Founder of French Stack, I create complete IT solutions."}]},{"type":"p","children":[{"type":"text","text":"Full-stack developer, I mainly work on frontend projects using Angular, React, or Vue."}]},{"type":"p","children":[{"type":"text","text":"Passionate about design, here are some of my "},{"type":"a","url":"https://www.artstation.com/nicolas-roehm","title":"ArtStation - Nicolas Roehm","children":[{"type":"text","text":"graphic designs"}]},{"type":"text","text":"."}]},{"type":"mdxJsxFlowElement","name":"socialLinks","children":[{"type":"text","text":""}],"props":{"links":[{"icon":"gitHub","link":"https://github.com/NicolasRoehm"},{"icon":"stackOverflow","link":"https://stackoverflow.com/users/7462178/nicolas-roehm?tab=profile"},{"icon":"linkedIn","link":"https://en.linkedin.com/in/nicolas-roehm-bettcher"}]}}]},"heroSubtitleIsInline":true,"heroHasBackground":false,"heroImage":"/images/nicolas-roehm-bettcher.png","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(312deg, #0800ff 0%, #4300ff00 70%)","heroMaxWidth":"","heroMs":"25%","heroTitleMb":"0.5rem","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"#fff0","navbarBorderColor":"","navbarLinkActive":"#6785be","navbarLinkHover":"#6785be"},"imageAlt":"nicolas roehm bettcher","imageWidth":0,"imageHeight":0},"seoSection":{"metaTitle":"Nicolas Roehm, Software Engineer","metaDescription":"Passionate about computing, I design complete websites: design, development, SEO, e-reputation, e-mailing, hosting.","metaTags":"Nicolas Roehm, Software Engineer, web, mobile, website","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2024-12-09T00:39:02.584Z","localeCode":"en","slug":"nicolas-roehm-bettcher","url":"/en/nicolas-roehm-bettcher","ogId":"nicolas-roehm-bettcher-en","ogImagePath":"/og/nicolas-roehm-bettcher-en.png","type":"Author","title":"Nicolas Roehm-Bettcher","avatar":"/images/nicolas-roehm-avatar.png","lname":"Roehm","fname":"Nicolas","name":"Nicolas Roehm","translations":[{"localeCode":"fr","title":"Nicolas Roehm-Bettcher","slug":"nicolas-roehm-bettcher","url":"/fr/nicolas-roehm-bettcher"}]},"translations":[{"localeCode":"fr","title":"Fallow : la qualité de code au rythme des agents IA","slug":"fallow-codebase-intelligence-typescript","url":"/fr/blog/fallow-codebase-intelligence-typescript"}],"tags":[{"id":"content/tags/en/typescript.mdx","localeCode":"en","title":"TypeScript","slug":"typescript","url":"/en/blog/typescript"}]},{"id":"content/articles/en/angular-form-validation-compare-multiple-fields.mdx","heroSection":{"heroTitle":"Comparing Multiple Fields","heroSubtitle":"","heroBadge":"Angular Form Validation","heroColoredWords":"1","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"How to validate two form fields by comparing them?"}]},{"type":"p","children":[{"type":"text","text":"Let's verify multiple fields with a high-level validator!"}]}]},"heroSubtitleIsInline":false,"heroHasBackground":false,"heroImage":"/images/angular-form-validation.png","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(180deg, transparent 0%, #0e256ddb 17%, #ff4444db 120%)","heroMaxWidth":"","heroMs":"","heroTitleMb":"","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"","navbarBorderColor":"","navbarLinkActive":"","navbarLinkHover":""},"imageAlt":"angular form validation","imageWidth":1344,"imageHeight":768},"seoSection":{"metaTitle":"Angular Form Validation: Comparing Multiple Fields","metaDescription":"How to validate two form fields by comparing them? Let's verify multiple fields with a high-level validator!","metaTags":"form, angular, validation, angular-validation","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2024-12-07T00:09:54.046Z","localeCode":"en","slug":"angular-form-validation-compare-multiple-fields","url":"/en/blog/angular-form-validation-compare-multiple-fields","ogId":"angular-form-validation-compare-multiple-fields-blog-en","ogImagePath":"/og/angular-form-validation-compare-multiple-fields-blog-en.png","type":"Article","title":"Comparing Multiple Fields with Angular","subtitle":"","browserUrl":"","textPreview":{"type":"root","children":[]},"subdomainKey":"blog","subdomain":"blog","draft":false,"logoAlt":"","logoWidth":0,"logoHeight":0,"body":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Suppose our form has date fields "},{"type":"text","text":"startDate","code":true},{"type":"text","text":" and "},{"type":"text","text":"endDate","code":true},{"type":"text","text":", and we want to ensure that "},{"type":"text","text":"startDate","code":true},{"type":"text","text":" must be before "},{"type":"text","text":"endDate","code":true},{"type":"text","text":"."}]},{"type":"p","children":[{"type":"text","text":"To implement validations containing one or more sibling controls, we need to define the validation function at a higher level than the sibling controls."}]},{"type":"mdxJsxFlowElement","name":"codeHeader","children":[{"type":"text","text":""}],"props":{"filePath":"app / src / pages / form-example / form-example.component.ts","fileName":"form-example.component.ts","svgFile":"typescript"}},{"type":"code_block","lang":"typescript","value":"ngOnInit() : void\n{\n  this.formGroup = this.formBuilder.group(\n  {\n    startDate : new FormControl({\n      value    : null,\n      disabled : false\n    }, [ Validators.required ]),\n    endDate : new FormControl({\n      value    : null,\n      disabled : false\n    }, [ Validators.required ]),\n  },\n  // NOTE High-level validator\n  { validator : DateValidator.dateRangeValidator });\n}","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Then, we define a custom validator in a separate file, for example "},{"type":"text","text":"date.validator.ts","code":true},{"type":"text","text":"."}]},{"type":"mdxJsxFlowElement","name":"codeHeader","children":[{"type":"text","text":""}],"props":{"fileName":"date.validator.ts","filePath":"app / src / shared / validators / date.validator.ts","svgFile":"typescript"}},{"type":"code_block","lang":"typescript","value":"// Angular modules\nimport { Injectable }       from '@angular/core';\nimport { AbstractControl }  from '@angular/forms';\nimport { ValidationErrors } from '@angular/forms';\n\n@Injectable({\n  providedIn : 'root'\n})\nexport class DateValidator\n{\n  constructor() {}\n\n  public static dateRangeValidator(control : AbstractControl) : ValidationErrors | null\n  {\n    // NOTE Safety check\n    if (!control.get('startDate').value || !control.get('endDate').value)\n      return null;\n\n    // NOTE Field comparison\n    // const mStart  = moment(control.get('startDate').value);\n    // const mEnd    = moment(control.get('endDate').value);\n    // const isValid = mStart.isBefore(mEnd);\n\n    // NOTE Invalid\n    if (!isValid)\n      return { invalidDateRange : true };\n\n    // NOTE Valid\n    return null;\n  }\n}","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"If invalid, return an error object (with any arbitrary name), such as "},{"type":"text","text":"return { invalidEndDate: true }","code":true},{"type":"text","text":"."}]},{"type":"p","children":[{"type":"text","text":"Make sure it always returns "},{"type":"text","text":"null","code":true},{"type":"text","text":" for valid or irrelevant cases, and a non-null object in cases where an error should be triggered on the "},{"type":"text","text":"formGroup","code":true},{"type":"text","text":"."}]},{"type":"p","children":[{"type":"text","text":"To display the error in our view, we use the "},{"type":"text","text":"invalidDateRange","code":true},{"type":"text","text":" key returned by our validator."}]},{"type":"mdxJsxFlowElement","name":"codeHeader","children":[{"type":"text","text":""}],"props":{"fileName":"form-example.component.html","filePath":"app / src / pages / form-example / form-example.component.html","svgFile":"html"}},{"type":"code_block","lang":"html","value":"<div *ngIf=\"formGroup.hasError('invalidDateRange')\">\n  The start date is not before the end date\n</div>","children":[{"type":"text","text":""}]}]},"dateCreate":"2021-03-17T10:46:42.000Z","dateUpdate":"2021-09-15T10:57:26.000Z","author":{"id":"content/authors/en/nicolas-roehm-bettcher.mdx","heroSection":{"heroTitle":"Nicolas Roehm","heroSubtitle":"Software Engineer","heroBadge":"","heroColoredWords":"","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Founder of French Stack, I create complete IT solutions."}]},{"type":"p","children":[{"type":"text","text":"Full-stack developer, I mainly work on frontend projects using Angular, React, or Vue."}]},{"type":"p","children":[{"type":"text","text":"Passionate about design, here are some of my "},{"type":"a","url":"https://www.artstation.com/nicolas-roehm","title":"ArtStation - Nicolas Roehm","children":[{"type":"text","text":"graphic designs"}]},{"type":"text","text":"."}]},{"type":"mdxJsxFlowElement","name":"socialLinks","children":[{"type":"text","text":""}],"props":{"links":[{"icon":"gitHub","link":"https://github.com/NicolasRoehm"},{"icon":"stackOverflow","link":"https://stackoverflow.com/users/7462178/nicolas-roehm?tab=profile"},{"icon":"linkedIn","link":"https://en.linkedin.com/in/nicolas-roehm-bettcher"}]}}]},"heroSubtitleIsInline":true,"heroHasBackground":false,"heroImage":"/images/nicolas-roehm-bettcher.png","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(312deg, #0800ff 0%, #4300ff00 70%)","heroMaxWidth":"","heroMs":"25%","heroTitleMb":"0.5rem","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"#fff0","navbarBorderColor":"","navbarLinkActive":"#6785be","navbarLinkHover":"#6785be"},"imageAlt":"nicolas roehm bettcher","imageWidth":0,"imageHeight":0},"seoSection":{"metaTitle":"Nicolas Roehm, Software Engineer","metaDescription":"Passionate about computing, I design complete websites: design, development, SEO, e-reputation, e-mailing, hosting.","metaTags":"Nicolas Roehm, Software Engineer, web, mobile, website","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2024-12-09T00:39:02.584Z","localeCode":"en","slug":"nicolas-roehm-bettcher","url":"/en/nicolas-roehm-bettcher","ogId":"nicolas-roehm-bettcher-en","ogImagePath":"/og/nicolas-roehm-bettcher-en.png","type":"Author","title":"Nicolas Roehm-Bettcher","avatar":"/images/nicolas-roehm-avatar.png","lname":"Roehm","fname":"Nicolas","name":"Nicolas Roehm","translations":[{"localeCode":"fr","title":"Nicolas Roehm-Bettcher","slug":"nicolas-roehm-bettcher","url":"/fr/nicolas-roehm-bettcher"}]},"translations":[{"localeCode":"fr","title":"Comparer plusieurs champs avec Angular","slug":"angular-validation-formulaire-comparer-plusieurs-champs","url":"/fr/blog/angular-validation-formulaire-comparer-plusieurs-champs"}],"tags":[{"id":"content/tags/en/angular.mdx","localeCode":"en","title":"Angular","slug":"angular","url":"/en/blog/angular"}]},{"id":"content/articles/en/javascript-librairies-youtube-like.mdx","heroSection":{"heroTitle":"Javascript Libraries #1: Youtube","heroSubtitle":"","heroBadge":"","heroColoredWords":"4","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Discover the best \"Youtube-like\" plugins and scripts for your website!"}]}]},"heroSubtitleIsInline":false,"heroHasBackground":false,"heroImage":"/images/js-libs-youtube-1.png","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(180deg, #010093eb 0%, #ffd400 100%)","heroMaxWidth":"","heroMs":"0","heroTitleMb":"","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"","navbarBorderColor":"","navbarLinkActive":"","navbarLinkHover":""},"imageAlt":"js libs youtube 1","imageWidth":1344,"imageHeight":768},"seoSection":{"metaTitle":"Youtube: JS Plugins & Scripts #1","metaDescription":"This week, JS libs introduces you to Youtube-like plugins for your website.","metaTags":"youtube js, youtube javascript, youtube libraries, youtube script, youtube plugin, youtube jquery","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2024-12-09T00:41:07.231Z","localeCode":"en","slug":"javascript-librairies-youtube-like","url":"/en/blog/javascript-librairies-youtube-like","ogId":"javascript-librairies-youtube-like-blog-en","ogImagePath":"/og/javascript-librairies-youtube-like-blog-en.png","type":"Article","title":"JS Libs #1: Youtube","subtitle":"","browserUrl":"","textPreview":{"type":"root","children":[]},"subdomainKey":"blog","subdomain":"blog","draft":false,"logoAlt":"","logoWidth":0,"logoHeight":0,"icon":"play-btn","body":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Discover a selection of "},{"type":"text","text":"web resources","bold":true},{"type":"text","text":", "},{"type":"text","text":"scripts","bold":true},{"type":"text","text":", "},{"type":"text","text":"plugins","bold":true},{"type":"text","text":", and "},{"type":"text","text":"CSS tools","bold":true},{"type":"text","text":" to customize your website! The first episode of "},{"type":"text","text":"JS libs","bold":true},{"type":"text","text":" is dedicated to "},{"type":"text","text":"Youtube plugins","bold":true},{"type":"text","text":". Happy customizing!"}]},{"type":"h3","children":[{"type":"text","text":"Youtube Loading Bar"}]},{"type":"p","children":[{"type":"text","text":"A small jQuery plugin that allows you to add a \"Youtube-like\" loading bar to all your ajax links."}]},{"type":"h4","children":[{"type":"text","text":"Initialization Example"}]},{"type":"code_block","lang":"javascript","value":"$('.ajax-link').loadingbar({\n  replaceURL : true, // You can visibly change the URL of the browser to reflect the clicked links by toggling this to true\n  target     : '#loadingbar-frame', // The container's selector where you want the ajax result to appear\n  direction  : 'right', // The direction where the the loading bar will progress\n});","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"img","url":"/images/you-tube-loading-bar.png","alt":"Script Web : Youtube Loading Bar","caption":"845x475","children":[{"type":"text","text":""}]}]},{"type":"mdxJsxFlowElement","name":"buttons","children":[{"type":"text","text":""}],"props":{"buttons":[{"icon":"gitHub","label":"GitHub","link":"https://github.com/peachananr/loading-bar","style":"primary"},{"icon":"","label":"Demo","link":"http://peachananr.github.io/loading-bar/demo.html","style":"light"}]}},{"type":"h3","children":[{"type":"text","text":"Tubular.js"}]},{"type":"p","children":[{"type":"text","text":"Tubular is a jQuery plugin that allows you to set a YouTube video as the background of your webpage. Simply integrate the plugin into your site, link your page's container to the ID of your YouTube video, and you're set!"}]},{"type":"h4","children":[{"type":"text","text":"Initialization example"}]},{"type":"code_block","lang":"javascript","value":"$('#wrapper').tubular({ videoId : 'aJTGyyRXDh4' }); // where videoId is the YouTube ID","children":[{"type":"text","text":""}]},{"type":"h4","children":[{"type":"text","text":"Configurable options"}]},{"type":"code_block","lang":"javascript","value":"ratio            : 16 / 9, // Usually either 4/3 or 16/9 -- tweak as needed\nvideoId          : 'aJTGyyRXDh4',\nmute             : true,\nrepeat           : true,\nwidth            : $(window).width(), // No need to override\nwrapperZIndex    : 99,\nplayButtonClass  : 'tubular-play',\npauseButtonClass : 'tubular-pause',\nmuteButtonClass  : 'tubular-mute',\nvolumeUpClass    : 'tubular-volume-up',\nvolumeDownClass  : 'tubular-volume-down',\nincreaseVolumeBy : 10, // Increment value; volume range is 1-100\nstart            : 0 // Starting position in seconds","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"img","url":"/images/you-tube-video-background.png","caption":"845x475","children":[{"type":"text","text":""}],"alt":"You Tube Video Background"}]},{"type":"mdxJsxFlowElement","name":"buttons","children":[{"type":"text","text":""}],"props":{"buttons":[{"icon":"google","label":"Google Code","link":"https://code.google.com/archive/p/jquery-tubular/","style":"primary"}]}},{"type":"h3","children":[{"type":"text","text":"PreViewTube"}]},{"type":"p","children":[{"type":"text","text":"A small jQuery plugin to animate thumbnails of your YouTube videos on hover or continuously. The speed of image transitions can be adjusted for smoother previews."}]},{"type":"h4","children":[{"type":"text","text":"Initialization example"}]},{"type":"code_block","lang":"javascript","value":"$('.preViewTube').PreViewTube();","children":[{"type":"text","text":""}]},{"type":"h4","children":[{"type":"text","text":"Configurable options"}]},{"type":"code_block","lang":"javascript","value":"interval: 500, // The animation rate in ms (default: 500ms)\nmode     : 'constant' // How the animation should run 'constant' or 'hover' (default : hover)","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"img","url":"/images/you-tube-thumbnail-images.png","caption":"845x475","children":[{"type":"text","text":""}],"alt":"You Tube Thumbnail Images"}]},{"type":"mdxJsxFlowElement","name":"buttons","children":[{"type":"text","text":""}],"props":{"buttons":[{"icon":"gitHub","label":"GitHub","link":"https://github.com/vool/PreViewTube.js","style":"primary"},{"icon":"","label":"Demo","link":"http://previewtube.vool.ie/","style":"light"}]}},{"type":"h3","children":[{"type":"text","text":"Youtube autoplay playlist"}]},{"type":"p","children":[{"type":"text","text":"This jQuery plugin enables automatic playback of YouTube playlists and also applies a cinematic effect to your videos by \"dimming the lights\" on your site! Numerous options and parameters are available to customize the appearance and playback mode of your videos."}]},{"type":"h4","children":[{"type":"text","text":"Initialization example"}]},{"type":"code_block","lang":"javascript","value":"$('#youtubevideo').youTubePlaylistResponsive({\n  listtype  : 'custom',\n  listvalue : 'gFftC9O9EZ0,-Fv-iUhLcys,Vv2YXjCWg1A,eIa7YxlHq3A'\n});","children":[{"type":"text","text":""}]},{"type":"h4","children":[{"type":"text","text":"Configurable options"}]},{"type":"code_block","lang":"javascript","value":"listtype        : 'search', // Choose between playlist, user_uploads, custom or search (max. 20 video's)\nlistvalue       : 'nature', // Playlist ID, channel name, ID's seperated by comma's (custom) or search for keywords\nautoplay        : false,    // If set to true the player will play onload\nshowrelated     : false,    // Show related movies at the end of the movie\nshowinfo        : true,     // Display thumbnail images for the videos in the playlist\nautohide        : false,    // Indicates whether the video controls will automatically hide after a video begins playing\ntheme           : false,    // Set the color scheme foer the player. true is white ad false is black\nmodestbranding  : true,     // Set to false to show the youtube logo in the player controll bar\niv_load_policy  : false,    // Setting to true will cause video annotations to be shown by default\nallowfullscreen : true,     // Show the fullscreen button\ncontrols        : true,     // This parameter indicates whether the video player controls will display\nhd              : false,    // Play the video's in HD at startup\nmaxwidth        : '',       // Here you can set the maxwidth in % or px\ncenter          : false,    // If maxwidth is set you can optional center the player\nlightsout       : true      // Mouseover the video turns out the light effect (background fading)","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"img","url":"/images/you-tube-autoplay-playlist.png","caption":"845x475","children":[{"type":"text","text":""}],"alt":"You Tube Autoplay Playlist"}]},{"type":"mdxJsxFlowElement","name":"buttons","children":[{"type":"text","text":""}],"props":{"buttons":[{"icon":"codeFile","label":"Documentation","link":"https://www.cfcms.nl/youtube-responsive/documentation/index.html#styles","style":"primary"},{"icon":"","label":"Demo","link":"https://www.cfcms.nl/youtube-responsive/index.html","style":"light"}]}}]},"dateCreate":"2016-05-23T09:56:46.000Z","dateUpdate":"2021-05-13T01:50:56.000Z","author":{"id":"content/authors/en/nicolas-roehm-bettcher.mdx","heroSection":{"heroTitle":"Nicolas Roehm","heroSubtitle":"Software Engineer","heroBadge":"","heroColoredWords":"","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Founder of French Stack, I create complete IT solutions."}]},{"type":"p","children":[{"type":"text","text":"Full-stack developer, I mainly work on frontend projects using Angular, React, or Vue."}]},{"type":"p","children":[{"type":"text","text":"Passionate about design, here are some of my "},{"type":"a","url":"https://www.artstation.com/nicolas-roehm","title":"ArtStation - Nicolas Roehm","children":[{"type":"text","text":"graphic designs"}]},{"type":"text","text":"."}]},{"type":"mdxJsxFlowElement","name":"socialLinks","children":[{"type":"text","text":""}],"props":{"links":[{"icon":"gitHub","link":"https://github.com/NicolasRoehm"},{"icon":"stackOverflow","link":"https://stackoverflow.com/users/7462178/nicolas-roehm?tab=profile"},{"icon":"linkedIn","link":"https://en.linkedin.com/in/nicolas-roehm-bettcher"}]}}]},"heroSubtitleIsInline":true,"heroHasBackground":false,"heroImage":"/images/nicolas-roehm-bettcher.png","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(312deg, #0800ff 0%, #4300ff00 70%)","heroMaxWidth":"","heroMs":"25%","heroTitleMb":"0.5rem","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"#fff0","navbarBorderColor":"","navbarLinkActive":"#6785be","navbarLinkHover":"#6785be"},"imageAlt":"nicolas roehm bettcher","imageWidth":0,"imageHeight":0},"seoSection":{"metaTitle":"Nicolas Roehm, Software Engineer","metaDescription":"Passionate about computing, I design complete websites: design, development, SEO, e-reputation, e-mailing, hosting.","metaTags":"Nicolas Roehm, Software Engineer, web, mobile, website","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2024-12-09T00:39:02.584Z","localeCode":"en","slug":"nicolas-roehm-bettcher","url":"/en/nicolas-roehm-bettcher","ogId":"nicolas-roehm-bettcher-en","ogImagePath":"/og/nicolas-roehm-bettcher-en.png","type":"Author","title":"Nicolas Roehm-Bettcher","avatar":"/images/nicolas-roehm-avatar.png","lname":"Roehm","fname":"Nicolas","name":"Nicolas Roehm","translations":[{"localeCode":"fr","title":"Nicolas Roehm-Bettcher","slug":"nicolas-roehm-bettcher","url":"/fr/nicolas-roehm-bettcher"}]},"translations":[{"localeCode":"fr","title":"JS libs #1 : Youtube","slug":"javascript-librairies-youtube-like","url":"/fr/blog/javascript-librairies-youtube-like"}],"tags":[{"id":"content/tags/en/jquery.mdx","localeCode":"en","title":"jQuery","slug":"jquery","url":"/en/blog/jquery"}]}],"tags":[{"id":"content/tags/en/angular.mdx","heroSection":{"heroTitle":"Angular","heroSubtitle":"","heroBadge":"","heroColoredWords":"","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"TypeScript-based open-source web application framework led by Google"}]},{"type":"p","children":[{"type":"text","text":"and by a community of individuals and corporations"}]}]},"heroSubtitleIsInline":false,"heroHasBackground":false,"heroImage":"/images/angular.svg","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(140deg, rgb(0,69,145,0.83) 31%, rgb(221,7,49) 100%)","heroMaxWidth":"","heroMs":"","heroTitleMb":"","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"","navbarBorderColor":"","navbarLinkActive":"","navbarLinkHover":""},"imageAlt":"angular","imageWidth":0,"imageHeight":0},"seoSection":{"metaTitle":"Angular","metaDescription":"TypeScript-based open-source web application framework led by Google and by a community of individuals and corporations","metaTags":"Angular, Typescript, Material, Bootstrap","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2023-08-18T08:52:56.731Z","localeCode":"en","slug":"angular","url":"/en/blog/angular","ogId":"angular-blog-en","ogImagePath":"/og/angular-blog-en.png","type":"Tag","title":"Angular","subdomainKey":"blog","subdomain":"blog","translations":[{"localeCode":"fr","title":"Angular","slug":"angular","url":"/fr/blog/angular"}]},{"id":"content/tags/en/jquery.mdx","heroSection":{"heroTitle":"jQuery","heroSubtitle":"","heroBadge":"","heroColoredWords":"","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"jQuery is an open-source JavaScript library designed to simplify HTML DOM tree traversal and manipulation, as well as event handling, CSS animation, and Ajax"}]}]},"heroSubtitleIsInline":false,"heroHasBackground":false,"heroImage":"/images/jquery-logo.svg","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(140deg, rgba(0,69,145,0) 31%, rgba(0,174,255,100) 100%)","heroMaxWidth":"860px","heroMs":"","heroTitleMb":"","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"","navbarBorderColor":"","navbarLinkActive":"","navbarLinkHover":""},"imageAlt":"jquery logo","imageWidth":0,"imageHeight":0},"seoSection":{"metaTitle":"jQuery","metaDescription":"jQuery is an open-source JavaScript library designed to simplify HTML DOM tree traversal and manipulation, event handling, CSS animation, Ajax request","metaTags":"jQuery, Javascript, library, DOM HTML","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2024-12-08T19:30:13.969Z","localeCode":"en","slug":"jquery","url":"/en/blog/jquery","ogId":"jquery-blog-en","ogImagePath":"/og/jquery-blog-en.png","type":"Tag","title":"jQuery","subdomainKey":"blog","subdomain":"blog","translations":[{"localeCode":"fr","title":"jQuery","slug":"jquery","url":"/fr/blog/jquery"}]},{"id":"content/tags/en/typescript.mdx","heroSection":{"heroTitle":"TypeScript","heroSubtitle":"","heroBadge":"","heroColoredWords":"","heroBreakTitle":"","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Open-source typed superset of JavaScript,"}]},{"type":"p","children":[{"type":"text","text":"delivering robustness, maintainability, and software architecture excellence."}]}]},"heroSubtitleIsInline":false,"heroHasBackground":false,"heroImage":"/images/site-internet-web-development-agency.png","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(140deg, #1b3a6b 0%, #3178c6 100%)","heroMaxWidth":"","heroMs":"","heroTitleMb":"","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"","navbarBorderColor":"","navbarLinkActive":"","navbarLinkHover":""},"imageAlt":"site internet web development agency","imageWidth":0,"imageHeight":0},"seoSection":{"metaTitle":"TypeScript","metaDescription":"Typed superset of JavaScript designed to build scalable, robust and maintainable modern web applications.","metaTags":"TypeScript, JavaScript, static typing, codebase intelligence, code quality","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2026-08-26T09:00:00.000Z","localeCode":"en","slug":"typescript","url":"/en/blog/typescript","ogId":"typescript-blog-en","ogImagePath":"/og/typescript-blog-en.png","type":"Tag","title":"TypeScript","subdomainKey":"blog","subdomain":"blog","translations":[{"localeCode":"fr","title":"TypeScript","slug":"typescript","url":"/fr/blog/typescript"}]}],"pages":[0],"curPage":1,"page":{"id":"content/subdomains/en/blog.mdx","heroSection":{"heroTitle":"Digital news","heroSubtitle":"","heroBadge":"","heroColoredWords":"2","heroBreakTitle":"","heroShape":"shiny","heroGradient":"business-gradient","heroDescription":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Our online magazine presents new generation "},{"type":"text","text":"web trends","bold":true},{"type":"text","text":":"}]},{"type":"p","children":[{"type":"text","text":"design, SEO and SEM, marketing, development, optimization ..."}]},{"type":"p","children":[{"type":"text","text":"Discover our articles dedicated to "},{"type":"text","text":"new technologies","bold":true},{"type":"text","text":" and "},{"type":"text","text":"web standards","bold":true},{"type":"text","text":"!"}]},{"type":"p","children":[{"type":"text","text":"Subscribe via email or follow us on social networks to stay tuned about web news."}]}]},"heroSubtitleIsInline":false,"heroHasBackground":false,"heroImage":"/images/blog-news-web.jpg","heroVideoBackground":"","heroStyle":{"heroBg":"linear-gradient(353deg, rgba(255,129,0,0.64) 0%, #0018ffe0 120%)","heroMaxWidth":"","heroMs":"","heroTitleMb":"","heroTitleColor":"","heroContentBg":"","heroContentAlign":"","heroContentBlur":"","heroBlurImage":"","navbarBg":"","navbarBorderColor":"","navbarLinkActive":"","navbarLinkHover":""},"imageAlt":"blog news web","imageWidth":0,"imageHeight":0},"seoSection":{"metaTitle":"Digital news","metaDescription":"Online magazine to learn the Web, find resources, browse trends and enjoy a hot coffee","metaTags":"Web Inspiration, Tutorials, web trends","socialImageWidth":0,"socialImageHeight":0},"heroUpdatedAt":"2023-08-18T08:52:56.731Z","localeCode":"en","slug":"blog","url":"/en/blog","ogId":"blog-en","ogImagePath":"/og/blog-en.png","type":"Subdomain","title":"Blog","subdomainKey":"blog","subdomain":"blog","translations":[{"localeCode":"fr","title":"Blog","slug":"blog","url":"/fr/blog"}],"canShare":true,"canComment":true,"hasAuthor":true,"tagsInPanel":true,"cardContainer":"col-md-6","cardTemplate":"default"},"global":{"id":"content/global/en/settings.json","localeCode":"en","header":{"nav":[{"href":"index","label":"Home"},{"href":"blog","label":"Blog"},{"href":"videos","label":"Videos"},{"href":"services","label":"Services"},{"href":"clients","label":"Clients"},{"href":"about","label":"About"},{"href":"contact-us","label":"Contact"}]},"footer":{"social":[{"website":"x","account":"RoehmNicolas"},{"website":"instagram","account":"roehm.nicolas"},{"website":"facebook","account":"thefrenchstack"},{"website":"youtube","account":"@frenchstack"}],"hasSocial":true,"nav":[{"title":"French Stack","links":[{"href":"clients","label":"Clients"},{"href":"about","label":"About"},{"href":"contact-us","label":"Contact"}]},{"title":"Services","links":[{"href":"services/graphic-design","label":"Design"},{"href":"services/web-mobile-development","label":"Development"},{"href":"services/web-marketing","label":"Marketing"},{"href":"services/it-training","label":"Training"}]},{"title":"Blog","links":[{"href":"blog/angular","label":"Angular"},{"href":"blog/jquery","label":"jQuery"}]},{"title":"Videos","links":[{"href":"videos/audiovisual-marketing","label":"Audiovisual Marketing"}]}]},"bottom":{"dateCreate":"2015-12-27T05:55:00.000Z","nav":[{"href":"legal-informations","label":"Legal informations"},{"href":"privacy-policy","label":"Privacy policy"}],"hasLinks":true},"contactInfo":{"contactMethods":[{"id":"email","icon":"envelope","value":"frenchstack@gmail.com"},{"id":"phone","icon":"phone","value":"0651570751"}]}}},"__N_SSG":true}