{"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:40:00.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 one constant tendency: "},{"type":"text","text":"extending what already exists","bold":true},{"type":"text","text":" rather than creating 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, the AI 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” remains an intention: without measurement, it has no way of knowing whether 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":": 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 did not cut at random to bring a number down: it isolated each "},{"type":"text","text":"business step","bold":true},{"type":"text","text":" in a dedicated function, with a name that says what it does, 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, every action of the agent gets harder: finding the right file forces it 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 no longer need to be spelled out in every prompt or checked during review: they are measured, and the verdict is binding on the agent. 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}