PageSourceSearch

https://www.jhipster.tech/assets/js/b304eacd.f12110a9.js

js jhipster.tech collected 2026-09-24 09:18:00 UTC 16,953 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkjhipster_website=globalThis.webpackChunkjhipster_website||[]).push([[2301],{77285(e,n,i){i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>l,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"modules/extending-and-customizing","title":"Blueprint Basics","description":"JHipster has support for plugins, and we call them blueprints and modules.","source":"@site/docs/modules/extending-and-customizing.mdx","sourceDirName":"modules","slug":"/modules/extending-and-customizing/","permalink":"/modules/extending-and-customizing/","draft":false,"unlisted":false,"editUrl":"https://github.com/jhipster/jhipster.github.io/tree/main/docs/modules/extending-and-customizing.mdx","tags":[],"version":"current","lastUpdatedAt":1449340800000,"frontMatter":{"title":"Blueprint Basics","slug":"/modules/extending-and-customizing/","last_update":{"date":"2015-12-05T18:40:00.000Z"}},"sidebar":"docsSidebar","previous":{"title":"Official blueprints","permalink":"/modules/official-blueprints/"},"next":{"title":"Creating a module","permalink":"/modules/creating-a-module/"}}');var t=i(74848),s=i(28453);const l={title:"Blueprint Basics",slug:"/modules/extending-and-customizing/",last_update:{date:new Date("2015-12-05T18:40:00.000Z")}},o=void 0,a={},c=[{value:"Basic rules for a JHipster blueprint",id:"basic-rules-for-a-jhipster-blueprint",level:2},{value:"Usage",id:"usage",level:2},{value:"Examples",id:"examples",level:2},{value:"Side-by-Side blueprint",id:"side-by-side-blueprint",level:2},{value:"Custom CLI",id:"custom-cli",level:2},{value:"Local Blueprint",id:"local-blueprint",level:2},{value:"Development and public API",id:"development-and-public-api",level:2},{value:"Application configuration:",id:"application-configuration",level:2},{value:"Constants:",id:"constants",level:2},{value:"Functions:",id:"functions",level:2},{value:"Running a Blueprint locally for development",id:"running-a-blueprint-locally-for-development",level:2},{value:"Registering a blueprint to the JHipster marketplace",id:"registering-a-blueprint-to-the-jhipster-marketplace",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["JHipster has support for ",(0,t.jsx)(n.code,{children:"plugins"}),", and we call them ",(0,t.jsx)(n.code,{children:"blueprints"})," and ",(0,t.jsx)(n.code,{children:"modules"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Prior to JHipster v7.9.0, ",(0,t.jsx)(n.code,{children:"modules"})," were Yeoman generators executed using ",(0,t.jsx)(n.code,{children:"yo"}),", extended ",(0,t.jsx)(n.code,{children:"generators-jhipster"}),"'s ",(0,t.jsx)(n.code,{children:"generator-base"})," class, and registered hooks to integrate into JHipster's workflow."]}),"\n",(0,t.jsxs)(n.p,{children:["As of JHipster v7.9.0, ",(0,t.jsx)(n.code,{children:"modules"})," are ",(0,t.jsx)(n.code,{children:"blueprints"})," with stand-alone generators (not blueprinted) and a custom CLI.\nWe will refer to them as standalone blueprints (or just blueprints) from now on."]}),"\n",(0,t.jsx)(n.h2,{id:"basic-rules-for-a-jhipster-blueprint",children:"Basic rules for a JHipster blueprint"}),"\n",(0,t.jsx)(n.p,{children:"JHipster blueprints:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"are NPM packages and Yeoman generators."}),"\n",(0,t.jsxs)(n.li,{children:["follow an extension of the Yeoman rules listed at ",(0,t.jsx)(n.a,{href:"https://yeoman.io/authoring/index.html",children:"https://yeoman.io/authoring/index.html"}),". Instead of being prefixed by ",(0,t.jsx)(n.code,{children:"generator-"}),", are prefixed with ",(0,t.jsx)(n.code,{children:"generator-jhipster-"}),", and instead of having just the ",(0,t.jsx)(n.code,{children:"yeoman-generator"})," keyword, and must have 2 keywords, ",(0,t.jsx)(n.code,{children:"yeoman-generator"})," and ",(0,t.jsx)(n.code,{children:"jhipster-blueprint"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"usage",children:"Usage"}),"\n",(0,t.jsx)(n.p,{children:"To use a blueprint, run the below command"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"jhipster --blueprints <blueprint name>\n"})}),"\n",(0,t.jsx)(n.p,{children:"Or use the custom provided CLI:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"jhipster-my-blueprint\n"})}),"\n",(0,t.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,t.jsx)(n.p,{children:"JHipster has many official blueprints, some examples:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Backend","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/jhipster/jhipster-kotlin",children:"JHipster Kotlin"})," blueprint replaces most of the server side Java code with equivalent Kotlin code."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/jhipster/jhipster-dotnetcore",children:"JHipster.NET"})," blueprint replaces the entire server side with .NET implementation."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-nodejs",children:"JHipster NodeJS"})," blueprint replaces the entire server side with NestJS implementation."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Backend Customization","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-native",children:"JHipster Native"})," blueprint customizes JHipster applications with Spring Native compatibility."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Frontend","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-svelte",children:"Svelte Hipster"})," blueprint replaces the entire client side with Svelte implementation."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Mobile","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-ionic",children:"JHipster Ionic"})," blueprint generates an Ionic application."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"side-by-side-blueprint",children:"Side-by-Side blueprint"}),"\n",(0,t.jsx)(n.p,{children:"Each generator can be a side-by-side (SBS) blueprint. A SBS blueprint doesn't change the original generator's behavior but can customize the behavior and the result.\nA SBS blueprint makes easier to supp
1ort multiple JHipster versions and port to a new JHipster version."}),"\n",(0,t.jsx)(n.p,{children:"To make the generator side-by-side, add this to the constructor:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:"this.sbsBlueprint = true;\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Example: ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-native/blob/bb9c042f6bc70a26ba8037e951c93dc1d1820983/generators/server/generator.mjs#L17",children:"server generator at Native Blueprint"}),".\nIn the example, the generator ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-native/blob/bb9c042f6bc70a26ba8037e951c93dc1d1820983/generators/server/generator.mjs#L26-L35",children:"customizes package.json"}),", ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-native/blob/bb9c042f6bc70a26ba8037e951c93dc1d1820983/generators/server/generator.mjs#L37-L40",children:"removes files"}),", ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-native/blob/bb9c042f6bc70a26ba8037e951c93dc1d1820983/generators/server/generator.mjs#L42-L186",children:"customizes the pom.xml"}),", ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-native/blob/bb9c042f6bc70a26ba8037e951c93dc1d1820983/generators/server/generator.mjs#L211-L307",children:"customizes Java files"}),", ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster-native/blob/bb9c042f6bc70a26ba8037e951c93dc1d1820983/generators/server/generator.mjs#L321-L329",children:"customizes Cypress"}),", and so on."]}),"\n",(0,t.jsxs)(n.p,{children:["A side-by-side blueprint can be used to create hooks and help migrate an existing module. This is covered in ",(0,t.jsx)(n.a,{href:"/modules/creating-a-module",children:"Creating a module"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"custom-cli",children:"Custom CLI"}),"\n",(0,t.jsxs)(n.p,{children:["Standalone blueprints can be executed using ",(0,t.jsx)(n.code,{children:"yo"}),", but ",(0,t.jsx)(n.code,{children:"yo"})," is aggressive in generators discovery\u2014which can be slow\u2014and lacks some improvements. The JHipster CLI provides help and JHipster integration.\nTherefore, we recommend using the ",(0,t.jsx)(n.code,{children:"jhipster"})," CLI or creating a custom CLI based on ",(0,t.jsx)(n.code,{children:"generator-jhipster"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"jhipster"})," command executes the ",(0,t.jsx)(n.code,{children:"generator-jhipster"})," version you have installed globally. A custom CLI will execute the dependent ",(0,t.jsx)(n.code,{children:"generator-jhipster"})," and will make sure to use the supported ",(0,t.jsx)(n.code,{children:"generator-jhipster"}),"'s version."]}),"\n",(0,t.jsxs)(n.p,{children:["A custom CLI allows you to execute a custom generator and is covered in ",(0,t.jsx)(n.a,{href:"/modules/creating-a-module",children:"Creating a module"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"local-blueprint",children:"Local Blueprint"}),"\n",(0,t.jsx)(n.p,{children:"An application can be kept updated more easily when customizations are generated by jhipster. A local blueprint is implemented with this purpose in mind."}),"\n",(0,t.jsxs)(n.p,{children:["The entire blueprint is implemented inside the application's ",(0,t.jsx)(n.code,{children:".blueprint"})," directory."]}),"\n",(0,t.jsx)(n.p,{children:"Some benefits:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"avoids or reduces conflicts when regenerating and upgrading."}),"\n",(0,t.jsx)(n.li,{children:"allows to bulk edit entities files."}),"\n",(0,t.jsx)(n.li,{children:"doesn't need to be published to a npm repository."}),"\n",(0,t.jsx)(n.li,{children:"full control of the jhipster workflow."}),"\n",(0,t.jsx)(n.li,{children:"easily generated with a single command."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"development-and-public-api",children:"Development and public API"}),"\n",(0,t.jsx)(n.p,{children:"We still lack published JSDoc API documentation, so you will need to refer to the source code."}),"\n",(0,t.jsx)(n.h2,{id:"application-configuration",children:"Application configuration:"}),"\n",(0,t.jsxs)(n.p,{children:["JHipster's configuration follows ",(0,t.jsx)(n.a,{href:"https://yeoman.io/authoring/storage.html",children:"Yeoman configuration"})," pattern and provides additional support for blueprint config."]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"config"})," and ",(0,t.jsx)(n.code,{children:"jhipsterConfig"})," properties store the common config and write to the ",(0,t.jsx)(n.code,{children:"generator-jhipster"})," key in the ",(0,t.jsx)(n.code,{children:".yo-rc.json"})," file.\nThe ",(0,t.jsx)(n.code,{children:"blueprintStorage"})," and ",(0,t.jsx)(n.code,{children:"blueprintConfig"})," properties store the blueprint-specific config and write to the ",(0,t.jsx)(n.code,{children:"generator-jhipster-(my-blueprint)"})," key in the ",(0,t.jsx)(n.code,{children:".yo-rc.json"})," file."]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"config"})," and ",(0,t.jsx)(n.code,{children:"blueprintStorage"})," are ",(0,t.jsx)(n.a,{href:"https://yeoman.github.io/generator/Storage.html",children:"Storage instances"}),",\nwhile ",(0,t.jsx)(n.code,{children:"jhipsterConfig"})," and ",(0,t.jsx)(n.code,{children:"blueprintConfig"})," are ",(0,t.jsx)(n.a,{href:"https://yeoman.github.io/generator/Storage.html#createProxy",children:"proxy objects"})," for ",(0,t.jsx)(n.code,{children:"config"})," and ",(0,t.jsx)(n.code,{children:"blueprintStorage"})," storages for convenience."]}),"\n",(0,t.jsx)(n.h2,{id:"constants",children:"Constants:"}),"\n",(0,t.jsxs)(n.p,{children:["You can use constants in ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster/blob/main/generators/generator-constants.js",children:(0,t.jsx)(n.code,{children:"generator-constants.js"})}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:"const javaDir = `${jhipsterConstants.SERVER_MAIN_SRC_DIR + this.packageFolder}/`;\nconst resourceDir = jhipsterConstants.SERVER_MAIN_RES_DIR;\nconst webappDir = jhipsterConstants.CLIENT_MAIN_SRC_DIR;\n"})}),"\n",(0,t.jsx)(n.h2,{id:"functions",children:"Functions:"}),"\n",(0,t.jsxs)(n.p,{children:["You can use all functions in ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/generator-jhipster/blob/main/generators/generator-base.js",children:"generator-base.js"}),":"]}),"\n",(0,t.jsx)(n.h2,{id:"running-a-blueprint-locally-for-development",children:"Running a Blueprint locally for development"}),"\n",(0,t.jsx)(n.p,{children:"While developing a blueprint, please note the below steps. They are very important."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Link your blueprint globally"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Note: If you do not want to link the blueprint (Step 3) to each project being created."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"cd generator-jhipster-my-blueprint\nnpm link\n"})}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["Link a development version of JHipster to your blueprint. Note: required only if you want to use a non-released JHipster version, like the ",(0,t.jsx)(n.code,{children:"main"})," branch or your own custom fork)"]}
1),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"cd generator-jhipster\nnpm link\n\ncd generator-jhipster-my-blueprint\nnpm link generator-jhipster\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Or install ",(0,t.jsx)(n.code,{children:"generator-jhipster"})," from git:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"cd generator-jhipster-my-blueprint\nnpm install jhipster/generator-jhipster\n"})}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["Create a new folder for the app to be generated, and run JHipster ignoring JHipster dependencies (otherwise a released version will be installed each time ",(0,t.jsx)(n.code,{children:"npm install/ci"})," is called)"]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"mkdir my-app && cd my-app\n\njhipster --blueprints my-blueprint --skip-jhipster-dependencies\n"})}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Once the blueprint/generator-jhipster is released, re-add the JHipster dependencies for reproducibility"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"jhipster --no-skip-jhipster-dependencies\n"})}),"\n",(0,t.jsx)(n.h2,{id:"registering-a-blueprint-to-the-jhipster-marketplace",children:"Registering a blueprint to the JHipster marketplace"}),"\n",(0,t.jsxs)(n.p,{children:["To make your blueprint available in ",(0,t.jsx)(n.a,{href:"/modules/marketplace",children:"the JHipster marketplace"}),", you need to make sure you have the two keywords ",(0,t.jsx)(n.code,{children:"yeoman-generator"})," and ",(0,t.jsx)(n.code,{children:"jhipster-blueprint"})," in your published npm ",(0,t.jsx)(n.code,{children:"package.json"}),".\nIf you find any entry in the marketplace that is not a JHipster module or blueprint, you can help to deny list it by adding it to the ",(0,t.jsx)(n.code,{children:"blacklistedModules"})," section of the ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/jhipster.github.io/blob/main/modules/marketplace/data/modules-config.json",children:(0,t.jsx)(n.code,{children:"modules-config.json file"})})," by doing a Pull Request to the ",(0,t.jsx)(n.a,{href:"https://github.com/jhipster/jhipster.github.io",children:"jhipster/jhipster.github.io project"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Once you publish your blueprint to NPM, your blueprint will become available in our marketplace."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},28453(e,n,i){i.d(n,{R:()=>l,x:()=>o});var r=i(96540);const t={},s=r.createContext(t);function l(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.