diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000000..d9d2ac2212 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,19 @@ +set -e + +cd docs + +npm run docs:build + +cd .vuepress/dist + +git init +git add -A +git commit -m 'deploy' + +# if you are deploying to https://.github.io +# git push -f git@github.com:vuevixens/vuevixens.github.io.git master + +# if you are deploying to https://.github.io/ +git push -f git@github.com:NataliaTepluhina/vue-storefront.git master:gh-pages + +cd - diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js new file mode 100644 index 0000000000..8bceed2974 --- /dev/null +++ b/docs/.vuepress/config.js @@ -0,0 +1,82 @@ +module.exports = { + base: '/vue-storefront/', + head: [['link', { rel: 'icon', href: '/favicon.png' }]], + themeConfig: { + repo: 'DivanteLtd/vue-storefront', + docsDir: 'docs', + editLinks: true, + nav: [ + { + text: 'YouTube', + link: 'https://www.youtube.com/channel/UCkm1F3Cglty3CE1QwKQUhhg', + }, + { + text: 'Medium', + link: 'https://medium.com/the-vue-storefront-journal', + }, + ], + sidebar: { + '/guide/': [ + '', + { + title: 'Installation', + collapsable: false, + children: [ + 'installation/linux-mac', + 'installation/windows', + 'installation/magento', + 'installation/production-setup', + ], + }, + { + title: 'Basics', + collapsable: false, + children: [ + 'basics/project-structure', + 'basics/configuration', + 'basics/contributing', + 'basics/modules', + 'basics/feature-list', + 'basics/recipes', + 'basics/typescript', + ], + }, + // { + // title: 'Vue Storefront core and themes', + // collapsable: false, + // children: [ + // 'core-themes/themes', + // 'core-themes/webpack', + // 'core-themes/core-components', + // 'core-themes/plugins', + // 'core-themes/vuex', + // 'core-themes/data', + // 'core-themes/extensions', + // ], + // }, + // { + // title: 'Data in Vue Storefront', + // collapsable: false, + // children: ['data/data'], + // }, + // { + // title: 'Working with extensions', + // collapsable: false, + // children: ['extensions/'], + // }, + // { + // title: 'Integrations', + // collapsable: false, + // children: ['integrations/magento', 'integrations/multistore'], + // }, + // { + // title: 'Core API Modules docs', + // collapsable: false, + // children: ['api-modules/cart-module'], + // }, + ], + }, + }, + title: 'Vue Storefront', + description: 'Headless PWA for eCommerce', +}; diff --git a/docs/.vuepress/public/Apple_iPhone_X.png b/docs/.vuepress/public/Apple_iPhone_X.png new file mode 100644 index 0000000000..65a84df374 Binary files /dev/null and b/docs/.vuepress/public/Apple_iPhone_X.png differ diff --git a/docs/.vuepress/public/favicon.png b/docs/.vuepress/public/favicon.png new file mode 100644 index 0000000000..b89b18e218 Binary files /dev/null and b/docs/.vuepress/public/favicon.png differ diff --git a/docs/.vuepress/public/logo.png b/docs/.vuepress/public/logo.png new file mode 100644 index 0000000000..afa00c3698 Binary files /dev/null and b/docs/.vuepress/public/logo.png differ diff --git a/docs/.vuepress/public/magento_1.png b/docs/.vuepress/public/magento_1.png new file mode 100644 index 0000000000..e322bbf1f5 Binary files /dev/null and b/docs/.vuepress/public/magento_1.png differ diff --git a/docs/.vuepress/public/magento_2.png b/docs/.vuepress/public/magento_2.png new file mode 100644 index 0000000000..200a11fdc5 Binary files /dev/null and b/docs/.vuepress/public/magento_2.png differ diff --git a/docs/.vuepress/public/magento_3.png b/docs/.vuepress/public/magento_3.png new file mode 100644 index 0000000000..2b3051e762 Binary files /dev/null and b/docs/.vuepress/public/magento_3.png differ diff --git a/docs/.vuepress/public/storefront.png b/docs/.vuepress/public/storefront.png new file mode 100644 index 0000000000..5c94d43070 Binary files /dev/null and b/docs/.vuepress/public/storefront.png differ diff --git a/docs/.vuepress/public/video-webcast-1.png b/docs/.vuepress/public/video-webcast-1.png new file mode 100644 index 0000000000..f2d79190a4 Binary files /dev/null and b/docs/.vuepress/public/video-webcast-1.png differ diff --git a/docs/.vuepress/public/vs-video.png b/docs/.vuepress/public/vs-video.png new file mode 100644 index 0000000000..eca5e4493b Binary files /dev/null and b/docs/.vuepress/public/vs-video.png differ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..34c9ea4594 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +--- +home: true +heroImage: /logo.png +actionText: Get Started → +actionLink: /guide/ +--- diff --git a/docs/guide/README.md b/docs/guide/README.md new file mode 100644 index 0000000000..bbe0f699d8 --- /dev/null +++ b/docs/guide/README.md @@ -0,0 +1,48 @@ +# About + +build:passed +![version](https://img.shields.io/badge/node-v8.x-blue.svg) +![Branch stable](https://img.shields.io/badge/stable%20branch-master-blue.svg) +![Branch Develop](https://img.shields.io/badge/dev%20branch-develop-blue.svg) +![Branch Develop](https://img.shields.io/badge/community%20chat-slack-FF1493.svg) + +Vue Storefront is a standalone PWA storefront for your eCommerce, possible to connect with any eCommerce backend (eg. Magento, Pimcore, Prestashop or Shopware) through the API. + +Vue Storefront is and always will be in the open source. Anyone can use and support the project, we want it to be a tool for the improvement of the shopping experience. +The project is in the **production ready** phase. + +## Video demo + +

+ + See how it works + +

+ +## Technical Webcast #1 - demo and the architecture + +

+ + Demo and the architecture of Vue Storefront + +

+ +- [Read on how to integrate it with Magento2](https://medium.com/@piotrkarwatka/vue-storefront-how-to-install-and-integrate-with-magento2-227767dd65b2), +- [Read how to create Vue Storefront theme](https://medium.com/@frakowski/developing-themes-in-vue-storefront-backend-agnostic-ecommerce-pwa-frontend-part-1-72ea3c939593), +- [Read the interviews with authors of first production deployments](https://medium.com/@piotrkarwatka/vue-storefront-on-production-interview-with-gogetgold-com-developers-71e4b48ef996) + +## Is it production ready? + +Yes! There are more than 10 implementations happening right now and one live shop. + +## Join the community on Slack + +If you have any questions or ideas feel free to join our slack: https://vuestorefront.slack.com via [invitation link](https://join.slack.com/t/vuestorefront/shared_invite/enQtMzA4MTM2NTE5NjM2LTI1M2RmOWIyOTk0MzFlMDU3YzJlYzcyYzNiNjUyZWJiMTZjZjc3MjRlYmE5ZWQ1YWRhNTQyM2ZjN2ZkMzZlNTg) + +## Roadmap + +We are planning 1-2 milestones ahead. Our milestones are based on requirements from community, partners and production implementations. + +[See the roadmap](https://github.com/DivanteLtd/vue-storefront/milestones). + +[Check the feature list of 1.0](../basics/feature-list.md). diff --git a/docs/guide/api-modules/cart-module.md b/docs/guide/api-modules/cart-module.md new file mode 100644 index 0000000000..4badd5a85f --- /dev/null +++ b/docs/guide/api-modules/cart-module.md @@ -0,0 +1,3 @@ +# Core API Modules docs + +_Work in progress_ diff --git a/docs/guide/basics/configuration.md b/docs/guide/basics/configuration.md new file mode 100644 index 0000000000..a42c6e71eb --- /dev/null +++ b/docs/guide/basics/configuration.md @@ -0,0 +1,704 @@ +# Configuration file explained + +Vue Storefront application uses the [node-config](https://github.com/lorenwest/node-config) npm module to manage configuration files. Configuration is stored in the `/config` directory within two JSON files: + +- `default.json` is a configuration file provided along with the core Vue Storefront code and updated with any new release of Vue Storefront. It contains the default values only and therefore it shoulnd't be modified within your specific Vue Storefront instance. +- `local.json` is the second configuration file which is `.gitignore`'d from repository. This is the place where you should store all instance-specific configuration variables. + +The structure of these files is exactly the same! Vue Storefront does kind of `Object.assign(default, local)` (but with the deep-merge). This means that the `local.json` overrides the `default.json` properties. + +:::tip NOTE +Please take a look at the `node-config` docs as the library is open for some other ways to modify the configuration (using for example the `ENV` variables). +::: + +:::tip NOTE +Currently, the configuration files are being processed by the webpack during the build process. This means that whenever you apply some configuration changes you shall re-build the app - even when using the `yarn dev` mode. +::: + +Please find the configuration properties reference below. + +## Server + +```json +"server": { + "host": "localhost", + "port": 3000 +}, +``` + +Vue Storefront starts a HTTP server to deliver the SSR (server side rendered) pages and static assets. It's node.js server located in the `core/scripts/server.js`. This is the host name and TCP port which Vue Storefront is being bind to. + +## Redis + +```json +"redis": { + "host": "localhost", + "port": 6379, + "db": 0 +}, +``` + +This is redis configuration for the output cache. See additional information [here](../data/ssr-cache.md) + +## GraphQL + +```json +"graphql":{ + "host": "localhost", + "port": 8080 +}, +``` + +This is optional GraphQL endpoint; we're now supporting graphQL for the [catalog](https://github.com/DivanteLtd/vue-storefront/blob/develop/doc/GraphQL%20Action%20Plan.md) and this section is being used when `server.api` is set to `graphql` (default is "api") + +## ElasticSearch + +```json +"elasticsearch": { + "httpAuth": "", + "host": "localhost:8080/api/catalog", + "index": "vue_storefront_catalog" +}, +``` + +Vue Storefront uses the Elastic Search Query Language to query for data. However, here you're putting the Vue Storefront API `/api/catalog` endpoint which is kind of Elastic Search Proxy (dealing with the taxes, security itd.). + +If your `vue-storefront-api` instance is running on the `localhost`, port `8080` then the correct elasticsearch endpoint is as presented here. + +## SSR + +```json +"ssr": { + "executeMixedinAsyncData": true +}, +``` + +By default, Vue Storefront themes are created by building set of components that "mixins" the core-components. For example, you have `/src/themes/default/pages/Product.vue` which inherits the `/core/pages/Product.js` by having this core component included in the `"mixins": [Product]` section. + +The SSR data is being completed in the `asyncData` static method. If this configuration parameter is set to `true` (which is default) Vue Storefront will run the `asyncData` methods in the following sequence: +`core/pages/Product.js` -> `asyncData` +`src/themes/default/pages/Product.vue` -> `asyncData` + +If it's set to `false`, then **just the** `src/themes/default/pages/Product.vue` -> `asyncData` will be executed. +This option is referenced in the [core/client-entry.ts](https://github.com/DivanteLtd/vue-storefront/blob/master/core/client-entry.ts) line: 85. + +## Default store code + +```json +"defaultStoreCode": "", +``` + +This option is used only in the [Multistore setup](../integrations/multistore.md). By default it's `''` but if you're running for example multi-instance Vue Storefront setup and the current instance shall be connected to the `en` store on the backend - please just set it so. This config variable is referenced in the [core/store/lib/multistore.ts](https://github.com/DivanteLtd/vue-storefront/blob/master/core/store/lib/multistore.ts) + +## Store views + +```json +"storeViews": { + "multistore": false, + "mapStoreUrlsFor": ["de", "it"], +``` + +If the `storeViews.multistore` is set to `true` you'll see the `LanguageSwitcher.vue` included in the footer and all the [multistore operations](../integrations/multistore.md) will be included in the request flow. + +You should add all the multistore codes to the `mapStoreUrlsFor` as this property is used by [core/store/lib/multistore.ts](https://github.com/DivanteLtd/vue-storefront/blob/master/core/store/lib/multistore.ts) -> `setupMultistoreRoutes` method to add the `//p/....` and other standard routes. By accesing them you're [instructing Vue Storefront to switch the current store](https://github.com/DivanteLtd/vue-storefront/blob/master/core/client-entry.ts) settings (i18n, api requests with specific storeCode etc...) + +`storeViews` section contains one or more additional store views configured to serve proper i18n translations, tax settings etc. Please find the docs for this section below. + +```json + "de": { + "storeCode": "de", +``` + +```json + "disabled": true, +``` + +If specific store is disabled it won't be used to populate the routing table and won't be displayed in the `Language/Switcher.vue`. + +```json + "storeId": 3, +``` + +This is the `storeId` as set in the backend panel. This parameter is being used by some API calls to get the specific store currency and/or tax settings. + +```json + "name": "German Store", +``` + +This is the store name as displayed in the `Language/Switcher.vue`. + +```json + "url": "/de", +``` + +This URL is used only in the `Switcher` component. Typically it equals just to `/`. Sometimes you may like to have the different store views running as separate Vue Storefront instances; even under different URL addresses. This is the situation when this property comes into action. Just take a look on how [Language/Switcher.vue](https://github.com/DivanteLtd/vue-storefront/blob/master/src/themes/default/components/core/blocks/Switcher/Language.vue) generates the list of the stores. + +```json + "elasticsearch": { + "host": "localhost:8080/api/catalog", + "index": "vue_storefront_catalog_de" + }, +``` + +ElasticSearch settings can be overriden in the specific `storeView` config. You can use different ElasticSearch instance powering specific `storeView`. + +```json + "tax": { + "sourcePriceIncludesTax": false, + "defaultCountry": "DE", + "defaultRegion": "", + "calculateServerSide": true + }, +``` + +Taxes section is used by the [core/store/lib/taxcalc.ts](https://github.com/DivanteLtd/vue-storefront/blob/master/core/store/lib/taxcalc.ts). When `sourcePricesIncludesTax` is set to `true` it means that the prices indexed in the ElasticSearch already consists of the taxes. If it's set to `false` the taxes will be calculated runtime. + +The `defaultCountry` and the `defaultRegion` settings are being used for finding the proper tax rate for the anonymous unidentified user (which country is not set yet). + +```json + "i18n": { + "fullCountryName": "Germany", + "fullLanguageName": "German", + "defaultLanguage": "DE", + "defaultCountry": "DE", + "defaultLocale": "de-DE", + "currencyCode": "EUR", + "currencySign": "EUR", + "dateFormat": "HH:mm D-M-YYYY" + } + } +}, +``` + +The internationalization settings are used by the translation engine (`defautlLocale`) and the [Language/Switcher.vue](https://github.com/DivanteLtd/vue-storefront/blob/master/src/themes/default/components/core/blocks/Switcher/Language.vue) (`fullCountryName`, `fullLanguageName`). `currencyCode` is used for some of the API calls (rendering prices mostly) and `currencySign` is being used for displaying the prices in the frontend. + +## Entities + +```json +"entities": { + "optimize": true, +``` + +If this option is set to true, Vue Storefront will be limiting the data got from the API endpoints to the `includeFields` and remove all the `excludeFields` as set for all the specific entities below. This option is set to `true` by default as the JSON objects could ... be of significant size! + +This option property is referenced in the [core/store/modules/product](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/product), [core/store/modules/category](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/category), [core/store/modules/attribute](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/attribute) + +```json + "twoStageCaching": true, +``` + +Vue Storefront caches all the data entities got from `vue-storefront-api` into indexedDB local cache. This is a key feature for providing users with the offline mode. Unfortunately, when the `entities.optimize` option is set to `true`, we cannot cache the optimized entities as they don't contain all the required information. + +In such a case we're using a strategy called `twoStageCaching` which works like it executes two parallel server requests at once to get the required product, category or attribute feeds. The first request is with the limited fields and the second is for full records. Only the second request is cached **but\*\*** the first (which typically ends-up faster) is used for displaying the Category or Product page. + +Please take a look at the [core/store/modules/category](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/category) for the reference. + +```json + "optimizeShoppingCart": true, +``` + +Vue Storefront product objects can be quite large ones. They consist of `configurable_children`, `media_gallery` and other information. Quite significant for rendering the Product and Category pages but not so useful in the Shopping cart. To limit the shopping cart size (as it's transferred to the server while making an order) this option is being used. + +Please take a look at the [core/store/modules/cart](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/cart). + +```json + "category": { + "includeFields": [ "children_data", "id", "children_count", "sku", "name", "is_active", "parent_id", "level", "url_key", "product_count" ] + }, + "attribute": { + "includeFields": [ "attribute_code", "id", "entity_type_id", "options", "default_value", "is_user_defined", "frontend_label", "attribute_id", "default_frontend_label", "is_visible_on_front", "is_visible", "is_comparable" ] + }, + "productList": { + "sort": "", + "includeFields": [ "type_id", "sku", "product_links", "tax_class_id", "special_price", "special_to_date", "special_from_date", "name", "price", "priceInclTax", "originalPriceInclTax", "originalPrice", "specialPriceInclTax", "id", "image", "sale", "new", "url_key", "status" ], + "excludeFields": [ "configurable_children", "description", "configurable_options", "sgn" ] + }, + "productListWithChildren": { + "includeFields": [ "type_id", "sku", "name", "tax_class_id", "special_price", "special_to_date", "special_from_date", "price", "priceInclTax", "originalPriceInclTax", "originalPrice", "specialPriceInclTax", "id", "image", "sale", "new", "configurable_children.image", "configurable_children.sku", "configurable_children.price", "configurable_children.special_price", "configurable_children.priceInclTax", "configurable_children.specialPriceInclTax", "configurable_children.originalPrice", "configurable_children.originalPriceInclTax", "configurable_children.color", "configurable_children.size", "configurable_children.id", "product_links", "url_key", "status"], + "excludeFields": [ "description", "sgn"] + }, + "product": { + "excludeFields": [ "updated_at", "created_at", "attribute_set_id", "tier_prices", "options_container", "msrp_display_actual_price_type", "has_options", "stock.manage_stock", "stock.use_config_min_qty", "stock.use_config_notify_stock_qty", "stock.stock_id", "stock.use_config_backorders", "stock.use_config_enable_qty_inc", "stock.enable_qty_increments", "stock.use_config_manage_stock", "stock.use_config_min_sale_qty", "stock.notify_stock_qty", "stock.use_config_max_sale_qty", "stock.use_config_max_sale_qty", "stock.qty_increments", "small_image"], + "includeFields": null + } +}, +``` + +These settings are used just to configure the optimization strategy for different entity types. Please take a look that we have `productListWithChildren` and the `product` configuration separately. The former one is used in the Category page -> `core/pages/Category.js` and the latter is used in the Product page ->`core/pages/Product.js` + +## Cart + +```json +"cart": { + "bypassCartLoaderForAuthorizedUsers": true,, +``` + +The cart loader bypass feature is there because we're posting orders to Magento asynchronously - it may happen that directly after placing an order, the Magento’s user still have the same quote id and after browsing thrpugh VS Store old items will be restored to the shopping cart. Now uou can disable this behaviour by setting `bypassCartLoaderForAuthorizedUsers` option to `false` + +```json +"cart": { + "server_merge_by_default": true, +``` + +Server cart is being synchronized with the client's cart in the Vue Storefront by default. When it's not set the Vue Storefront will execute the server cart merge algorithm anyway - but using the `dryRun` option which means that only the following event will be emitted: + +```js +EventBus.$emit('servercart-after-diff', { + diffLog: diffLog, + serverItems: serverItems, + clientItems: clientItems, + dryRun: event.dry_run, + event: event, +}); // send the difflog +``` + +In the event handler one can handle the merge process manually - for example displaying the proper information to the user before the real merge takes place. + +Please have a look at the [core/store/modules/cart](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/cart) for a reference. + +```json + "synchronize": true, +``` + +If it's set to `true` the `serverPull` Vuex method will be executed whenever user adds, removes or edits any product in the shopping cart. This method syncs the client's side shopping cart with the server side one. + +Please take a look at the [core/store/modules/cart](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/cart) for a reference. + +```json + "synchronize_totals": true, +``` + +Similarly to the `synchronize` option you may want to disable or enable (the default behaviour) the shopping cart totals sync with the backend platform. If it's set to `true`, the shopping cart totals will be overriden by the Magento, Pimcore or any other platform you're using totals whenever user will add, remove or change any item in the shopping cart. + +```json + "setCustomProductOptions": true, +``` + +If this option is set to `true`, in case of custom-options supporting products, Vue Storefront will add the main SKU to the shopping cart and set the `product_option` sub-object of the shopping cart item to currently configured set of custom options (for example, selected dates, checkboxes, captions or other values). + +```json + "setConfigurableProductOptions": true, +``` + +If this option is set to `true`, in case of configurable products, Vue Storefront will add the main SKU to the shopping cart and set the `product_option` sub-object of the shopping cart item to currently configured set of configurable options (for example color and size). Otherwise the simple product (accordingly to the selected configurable_options) will be added to the shopping cart instead. + +```json + "create_endpoint": "http://localhost:8080/api/cart/create?token={{token}}", + "updateitem_endpoint": "http://localhost:8080/api/cart/update?token={{token}}&cartId={{cartId}}", + "deleteitem_endpoint": "http://localhost:8080/api/cart/delete?token={{token}}&cartId={{cartId}}", + "pull_endpoint": "http://localhost:8080/api/cart/pull?token={{token}}&cartId={{cartId}}", + "totals_endpoint": "http://localhost:8080/api/cart/totals?token={{token}}&cartId={{cartId}}", + "paymentmethods_endpoint": "http://localhost:8080/api/cart/payment-methods?token={{token}}&cartId={{cartId}}", + "shippingmethods_endpoint": "http://localhost:8080/api/cart/shipping-methods?token={{token}}&cartId={{cartId}}", + "shippinginfo_endpoint": "http://localhost:8080/api/cart/shipping-information?token={{token}}&cartId={{cartId}}", + "collecttotals_endpoint": "http://localhost:8080/api/cart/collect-totals?token={{token}}&cartId={{cartId}}", + "deletecoupon_endpoint": "http://localhost:8080/api/cart/delete-coupon?token={{token}}&cartId={{cartId}}", + "applycoupon_endpoint": "http://localhost:8080/api/cart/apply-coupon?token={{token}}&cartId={{cartId}}&coupon={{coupon}}" +``` + +These endpoints should point to the `vue-storefront-api` instance and typically you're changing just the domain-name/base-url without touching the specific endpoint urls as it's related to the `vue-storefront-api` specifics. + +## Products + +```json +"products": { + "useShortCatalogUrls": false, +``` + +When this option is set to `true`, Vue Storefront will use the alternative routing for products and categories - without the `/p/` and `/c/` prefixes. it may be useful for the Search Engine Optimization purposes. + +```json + "useMagentoUrlKeys": false, +``` + +When `useMagentoUrlKeys` is set to `true` the `product.url_key` value will be used for product and category slugs used in the URL building process. Otherwise the slug will be generated based on the product or category name. +Please take a look at the [core/store/lib/search.ts](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/lib/search.ts) and [core/store/modules/category/mutations.ts](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/category/mutations.ts) for reference + +```json + "configurableChildrenStockPrefetchStatic": false, + "configurableChildrenStockPrefetchStaticPrefetchCount": 8, +``` + +Vue Storefront tries to dynamically get the stock quantities for simple products related to the configurable ones (products included in the `configurabe_children` array). If the `configurableChildrenStockPrefetchStatic` is set to `true`, the stock items are prefetched from the Category page level. Please take a look at the [core/store/modules/category/actions.ts](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/category/actions.ts). The second option - `configurableChildrenStockPrefetchStaticPrefetchCount` sets how many products in the category should be prefetched using this mechanism. + +```json + "configurableChildrenStockPrefetchDynamic": false, +``` + +In opposite to the static prefetching Vue Storefront could also prefetch the `configurable_children` stock items just for the products that are visible on the category Page. This option is used from the theme level - for example [src/themes/default/pages/Category.vue](https://github.com/DivanteLtd/vue-storefront/tree/master/src/themes/default/pages/Category.vue) + +```json + "filterUnavailableVariants": false, +``` + +By default Vue Storefront displays all the variants assigned with the configurable product, no matter if they are visible or not. Then by adding specific variant to the shopping cart the availability is being checked. You can switch this setting to `true` to prefetch the variants availability (see the options described above) and hide unavailable options. + +```json + "listOutOfStockProducts": false, +``` + +By default Vue Storefront is not displaying products with the stock availability = 'Out of the stock'. However it can be changed using this variable. Vue Storefront uses the `product.stock` object to access the product information availability. Please note that this information is updated just when the `mage2vuestorefront` updates the ElasticSearch index. + +```json + "preventConfigurableChildrenDirectAccess": true, +``` + +If this option is set to true (default) Vue Storefront will prevent accessing the simple products assigned with the configurable one. User will be redirected to the main configurable product in such a case. + +```json + "alwaysSyncPlatformPricesOver": false, +``` + +This property is used in the [core/store/modules/product/actions.ts](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/modules/product/actions.ts); if it's set to `true` Vue Storefront will query the `vue-storefront-api` endpoint (`/api/products/render-list`) to render the product prices for currently displayed product(s) **every time** user is about to display the product or category page. + +```json + "clearPricesBeforePlatformSync": false, +``` + +This is related to `alwaysSyncPlatformPricesOver` and whet it's set to true, the prices provided from the ElasticSearch will be always overriden to zero before rendering the dynamic prices. + +```json + "waitForPlatformSync": false, +``` + +This is related to `alwaysSyncPlatformPricesOver`. When true, Vue Storefront will wait for dynamic prices before rendering the page. Otherwise, the product and category pages will be rendered using the default (ElasticSearch based) prices and then asynchronously override them with current ones. + +```json + "setupVariantByAttributeCode": true, +``` + +This is a deprecated value - when set to false, Vue Storefront will be using `slugify(attribute.name)` instead of `attribute.attribute_code` to construct filter and product configurators. It was provided to maintain the backwards compatibility with some platforms that didn't provide the `attribute_code` property. Currently not used. + +```json + "endpoint": "http://localhost:8080/api/product", +``` + +This is the `vue-storefront-api` endpoint for rendering product lists. + +```json + "defaultFilters": ["color", "size", "price", "erin_recommends"], +``` + +`defaultFilters` array should contain **all** the filters that could be used in the [Sidebar menu filters](https://github.com/DivanteLtd/vue-storefront/tree/master/src/themes/default/components/core/blocks/Category/Sidebar.vue). + +```json + "sortByAttributes": { + "Latest": "updated_at", + "Price":"price" + }, +``` + +Here we have the sort field settings as they're displayed on the Category page. + +```json + "gallery": { + "mergeConfigurableChildren": true +``` + +Vue Storefront is feeding the Product page gallery with the combination of: `product.media_gallery`, `product.image` and the `product.configurable_children.image`. If set to `false` the Product page gallery shows the `product.media_gallery` of the selected variant. + +```json + "gallery": { + "variantsGroupAttribute": "color" +``` + +If `mergeConfigurableChildren` is set to `true` in some cases simple products attached to the configurable one have the same photos as the main one assigned. If this option is set to the name of any particular attribute assigned with `configurable_children`, images that Vue Storefront is getting will be grouped by the color (getting single color images from the `configurable_children` collection) + +```json + "gallery": { + "imageAttributes": ["image","thumbnail","small_image"] +``` + +Product attributes representing the images. We'll see it in the Product page gallery if `mergeConfigurableChildren` is set to `false` and the product is configured + +```json + "gallery": { + "width": 600, + "height": 744 +``` + +The dimensions of the images in the gallery. + +## Orders + +```json +"orders": { + "endpoint": "http://localhost:8080/api/order", +``` + +This property sets the URL of the order endpoint. Orders will be placed to this specific URL as soon as the internet connection is available. + +```json + "payment_methods_mapping": { + }, +``` + +This is simple map used in the [core/pages/Checkout.js](https://github.com/DivanteLtd/vue-storefront/tree/master/core/pages/Checkout.js) to map the payment methods provided by the backend service with the ones available to the Vue Storefront. Each payment method is a separate Vue Storefront extension and not all methods provided by the backend should necessarily be supported by the frontend. + +```json + "offline_orders": { + "notification" : { + "enabled": true, + "title" : "Order waiting!", + "message": "Click here to confirm the order that you made offline.", + "icon": "/assets/logo.png" + } + } +``` + +When user places the order in the Offline mode and agrees to receive push notifications, these variables are used to determine the look and feel of the notification. + +Please check the [core/service-worker/order.js](https://github.com/DivanteLtd/vue-storefront/tree/master/core/service-worker/order.js) for reference + +## Local Forage + +```json +"localForage": { + "defaultDrivers": { + "user": "LOCALSTORAGE", + "carts": "LOCALSTORAGE", + "orders": "LOCALSTORAGE", + "wishlist": "INDEXEDDB", + "categories": "INDEXEDDB", + "attributes": "INDEXEDDB", + "products": "INDEXEDDB", + "elasticCache": "INDEXEDDB", + "claims": "LOCALSTORAGE", + "compare": "INDEXEDDB", + "syncTasks": "INDEXEDDB", + "newsletterPreferences": "INDEXEDDB", + "ordersHistory": "INDEXEDDB", + "checkoutFieldValues": "LOCALSTORAGE" + } +}, +``` + +We're using [localForage](https://github.com/localForage/localForage) library for provide the persistance layer to Vue Storefront. `localForage` is great as it provides the compatibility fallbacks for the users not equipped with some specific storage methods (for example indexedDb). However, we may want to enforce some specific storage methods in the config. This is the place to set it up. + +## Users + +```json +"users": { + "autoRefreshTokens": true, + "endpoint": "http://localhost:8080/api/user", + "history_endpoint": "http://localhost:8080/api/user/order-history?token={{token}}", + "resetPassword_endpoint": "http://localhost:8080/api/user/reset-password", + "changePassword_endpoint": "http://localhost:8080/api/user/change-password?token={{token}}", + "login_endpoint": "http://localhost:8080/api/user/login", + "create_endpoint": "http://localhost:8080/api/user/create", + "me_endpoint": "http://localhost:8080/api/user/me?token={{token}}", + "refresh_endpoint": "http://localhost:8080/api/user/refresh" +}, +``` + +In the `users` section we can set the API endpoints for specific use-related operations. Most of the times you need just to change the basic url. + +When the `autoRefreshTokens` property is set to `true` (default) Vue Storefront will be trying to refresh the user tokens automatically when the session ends up. Please take a look at the [core/store/lib/task.ts](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/lib/task.ts) for reference. + +## Stock + +```json +"stock": { + "synchronize": true, + "allowOutOfStockInCart": true, + "endpoint": "http://localhost:8080/api/stock" +}, +``` + +The `stock` section configures how the Vue Storefront behaves **just when** the product is being added to the cart. By default, the request to `stock.endpoint` is being made asynchronously to the `add to cart` operation. When the `allowOutOfStockInCart` is set to `true`, and the product is no longer available, it will be removed from the cart (with a proper UI notification) shortly after the information become available to the Vue Storefront. + +## Images + +```json +"images": { + "baseUrl": "https://demo.vuestorefront.io/img/", + "productPlaceholder": "/assets/placeholder.jpg" +}, +``` + +This section is to set the default base url of product images. This should be a `vue-storefront-api` url - pointing to it's `/api/img` handler. Vue Storefront API is in charge of downloading the local image cache from the Magento/Pimcore backend and do the resize/crop/scale operations to optimize the images for mobile devices and the UI. + +## Install + +```json +"install": { + "is_local_backend": true, + "backend_dir": "../vue-storefront-api" +}, +``` + +This is just to be used in the [core/scripts/installer.js](https://github.com/DivanteLtd/vue-storefront/tree/master/core/scripts/installer.js) + +## Demo mode + +```json +"demomode": false, +``` + +When `demomode` is set to `true`, Vue Storefront will display the "Welcome to Vue Storefront demo" popup. + +## Taxes + +```json +"tax": { + "sourcePriceIncludesTax": false, + "defaultCountry": "DE", + "defaultRegion": "", + "calculateServerSide": true +}, +``` + +Taxes section is used by the [core/store/lib/taxcalc.ts](https://github.com/DivanteLtd/vue-storefront/tree/master/core/store/lib/taxcalc.ts). When `sourcePricesIncludesTax` is set to `true` it means that the prices indexed in the ElasticSearch already consists of the taxes. If it's set to `false` the taxes will be calculated runtime. + +The `defaultCountry` and the `defaultRegion` settings are being used for finding the proper tax rate for the anonymous unidentified user (which country is not set yet). + +## Shipping + +```json +"shipping": { + "methods": [ + { + "method_title": "DPD Courier", + "method_code": "flatrate", + "carrier_code": "flatrate", + "amount": 4, + "price_incl_tax": 5, + "default": true, + "offline": true + } + ] +}, +``` + +Available shipping methods when backend platform is not providing the dynamic list / or for the offline scenarios. + +## Internationalization + +```json + "i18n": { + "fullCountryName": "Germany", + "fullLanguageName": "German", + "defaultLanguage": "DE", + "defaultCountry": "DE", + "defaultLocale": "de-DE", + "currencyCode": "EUR", + "currencySign": "EUR", + "dateFormat": "HH:mm D-M-YYYY" + } +} +}, +``` + +Internationalization settings are used by the translation engine (`defautlLocale`) and the [Language/Switcher.vue](https://github.com/DivanteLtd/vue-storefront/tree/master/src/themes/default/components/core/blocks/Switcher/Language.vue) (`fullCountryName`, `fullLanguageName`). `currencyCode` is used for some of the API calls (rendering prices mostly) and `currencySign` is being used for displaying the prices in the frontend. + +## Mailchimp + +```json +"mailchimp": { + "endpoint": "http://localhost:8080/api/ext/mailchimp-subscribe/subscribe" +}, +``` + +This property is used by the mailchimp extension (See [src/extensions](https://github.com/DivanteLtd/vue-storefront/tree/master/src/extensions) for a reference). + +## Theme + +```json +"theme": "@vue-storefront/theme-default", +``` + +This is the currently applied theme path. After changing it Vue Storefront need to be rebuilt. + +## Analytics + +```json +"analytics": { + "id": false +}, +``` + +You can put your Google Analytics ID in here as to be used by the analytics extension. + +## Stripe + +```json +"stripe": { + "api_key": "my_example_api_key" +}, +``` + +Here you have the Stripe API key for being used with the `vsf-payment-stripe` extension. + +## CMS + +```json +"cms": { + "endpoint": "http://localhost:8080/api/ext/cms-data/cms{{type}}/{{cmsId}}" +} +``` + +This is the URL endpoint of the Snow.dog Magento2 CMS extensions - need to be set when using the [src/extensions/cms](https://github.com/DivanteLtd/vue-storefront/tree/master/src/extensions/cms) + +## Use price tiers + +```json +"usePriceTiers": false, +``` + +When set to `true` we're using Magento2 feature of tiered prices (individual prices set for client's groups). The prices are set in `product.tier_prices` property. + +## Boost + +```json +"boost": { + "name": 3, + "category.name": 1, + "short_description": 1, + "description": 1, + "sku": 1, + "configurable_children.sku": 1 +}, +``` + +This is a list of priorities for search feature (higher boost = more important search field). + +## Query + +```json +"query": { + "inspirations": { + "filter": [ + { + "key": "category.name", + "value" : { "eq": "Performance Fabrics" } + } + ] + }, + "newProducts": { + "filter": [ + { + "key": "category.name", + "value" : { "eq": "Tees" } + } + ] + }, + "coolBags": { + "filter": [ + { + "key": "category.name", + "value" : { "eq": "Women" } + } + ] + }, + "bestSellers": { + "filter": [ + { + "key": "category.name", + "value" : { "eq": "Tees" } + } + ] + } + } +``` + +Search queries used by specific components (for example Related products); the format of the query has been described [here](https://github.com/DivanteLtd/vue-storefront/blob/develop/doc/data/ElasticSearch%20Queries.md) diff --git a/docs/guide/basics/contributing.md b/docs/guide/basics/contributing.md new file mode 100644 index 0000000000..6ca6788ca6 --- /dev/null +++ b/docs/guide/basics/contributing.md @@ -0,0 +1,55 @@ +# How to Contribute + +Already a JS/Vue.js developer? Pick an issue, push a PR and instantly become a member of the vue-storefront contributors community. We've marked some issues as `Easy first pick` to make it easier for newcomers to begin! + +Thank you for your interest in, and engagement! + +## Branches + +You should fork the project or create branch for new features.The main branches used by the core team are: + +- `master` - where we store the stable release of the app (that can be deployed to our demo instances), +- `develop` - the most recent version of the app - kind of "nightly" build. + +Please use `develop` for development purposes as the `master` can be merged just as the new release is coming out (about once a month). + +## Issue reporting guidelines + +Always define type of issue: + +- Bug report +- Feature request + +While writing issues, please be as specific as possible. All requests regarding support with implementation or application setup should be sent to [contributors@vuestorefront.io](mailto:contributors@vuestorefront.io) + +If the issue is about some changes with particular theme, please prefix the issue with theme name (ex. `[default] change product tile background color`). + +## TypeScript + +We're introducing TypeScript to Vue Storefront core, so you can use it where it's appropriate - but please be pragmatic. Would be nice to TS features only in new modules and Vuex. +Here are some thoughts on how to use TS features in Vue Storefront: [TypeScript Action Plan](typescript.md). + +## Pull request checklist + +Here’s how to submit a pull request. **Pull request that dont meet this requirements will not be merged**. + +:::warning +**ALWAYS** use [Pull Request template](https://github.com/DivanteLtd/vue-storefront/blob/master/PULL_REQUEST_TEMPLATE.md), it's automatically added to each PR. +::: + +1. Fork the repository and clone it locally on the 'develop' branch. +2. Create a branch for your edits. Use the following branch naming conventions: + +- `bugfix/task-title` +- `feature/task-name` + +3. Describe what you've changed. Include screenshots of the new feature or the before and after if your changes include differences in HTML/CSS. Drag and drop the images into the body of your pull request. +4. Reference any relevant issues or supporting documentation in your PR (ex. `Issue: 39. Issue title.`). +5. If you are adding new feature, please provide documentation along with the PR. Also add it to [upgrade notes](https://github.com/DivanteLtd/vue-storefront/blob/master/doc/Upgrade%20notes.md) +6. If you are removing/renaming something or changing its behavior, please also include it in [upgrade notes](https://github.com/DivanteLtd/vue-storefront/blob/master/doc/Upgrade%20notes.md) +7. Test your changes! Run your changes against any existing tests and create new ones when needed. Make sure your changes don’t break the existing project. Make sure that your branch is passing Travis CI build. +8. If you have found a potential security vulnerability, please _do not_ report it on the public issue tracker. Instead, send it to us at [contributors@vuestorefront.io](mailto:contributors@vuestorefront.io). We will work with you to verify and fix it as soon as possible. + +## New features + +If you are making any new feature make sure it's adjusted to our new, modular approach. Read more [here](modules.md) diff --git a/docs/guide/basics/feature-list.md b/docs/guide/basics/feature-list.md new file mode 100644 index 0000000000..4a5ac8118f --- /dev/null +++ b/docs/guide/basics/feature-list.md @@ -0,0 +1,133 @@ +# Feature list + +Vue Storefront is Platform Agnostic Headless Frontend for eCommerce. Here we tried to put all the features available in 1.0 alltogether: + +## Vue Storefront unique features + +- 100% offline support - via in-browser IndexedDB database +- High speed with local caching (Service Workers + IndexedDB); avg. server response time < 0.3s; avg client-side rendering time < 2s +- Platform Agnostic - Magento2, Magento1, Pimcore supported out-of-the-box +- Offline Orders support (via in-browser queue) +- Single Page App User Experience with Server Side Rendering support for SEO +- Native app features - install on Home Screen (iOS, Android, Chrome), push notifications (via customization) +- NoSQL/ElasticSearch database backend +- Modern Vue.js based frontend - easy to design and customize, atomic-design, design-system backed +- It's a Framework - customizable via Extensions, Themes, easy to update with separated Core + +## Vue Storefront Magento2 support + +### Checkout, Payment, & Shipping + +- One-Page Online Checkout +- Integrated for Real-Time Shipping Rates +- SSL Security Support for All Online Order and Sensitive Transactions +- Online Tax and Shipping Calculation and Prior to Checkout Estimates +- Option to Create Account as Part of Online Checkout Process +- Configurable Saved Cart Expiration +- Multiple Shipping Address Management +- Destination Country Management +- Per Order and Per Item Flat Rate Shipping Option +- Free Shipping Functionality +- Manage Shipping by Weight and Destination + +### Search Engine Optimization (SEO) + +- SSR (Server Site Rendering) +- Light Footprint Design for Fast Load Time and Search Engine Optimization +- Search Engine Friendly URLs Including URL ReWrite Controls +- META Information Management at Product and Category Levels +- Available via customization: Auto-Generated Popular Search Terms Page + +### Analytics and Reporting + +- Integration with Google Analytics +- Admin Report Dashboard with Business Overview +- Sales Reports Including Total Sales and Returns +- Tax Reports +- Abandoned Shopping Cart Reports +- Best Viewed Products Reports +- Top Sold Products Report +- Low Stock Item Report +- Onsite Search Terms Report +- Product Reviews Report with RSS Support +- Tags Report with RSS Support +- Coupon Usage Report + +### Marketing Promotions and Tools + +- Newsletter Management +- Catalog Promotional Pricing and Controls +- Flexible Coupons Rule and Pricing Restrictions +- Free Shipping Promotion Management +- Bundled Products Options +- Customer Group Pricing +- New Items Promotional Tool +- On Page Upsells and Cross Sells +- Wishlist Management + +### Order Management + +Standard Magento2 features - all supported: + +- View, edit, create and fulfill orders from admin panel +- Create one or multiple invoices, shipments and credit memos per order to allow for split fulfillment +- Print invoices and packing slips +- Call Center (phone) order creation - includes ability to create new customer, or select existing customer and view - shopping cart, wishlist, last ordered items, and compared products list, as well as select addresses, give discounts and assign custom prices +- Create re-orders for customers from administration panel +- Email Notifications of Orders +- RSS feed of New Orders + +### Customer Service + +- Contact Us form +- Feature-rich Customer Accounts +- Order History with Status Updates +- Password Reset email from front-end and admin panel +- Order and Account Update Emails +- Standard Magento2 feature: Customizable Order Emails +- Standard Magento2 feature: Create and Edit Orders from the Admin Panel + +### Customer Accounts + +- Order status and history +- Re-orders from account +- Address Book with unlimited addresses +- Default Billing and Shipping addresses +- Wishlist +- Newsletter Subscription management + +### Catalog Management Support + +- Inventory Management with Backordered items, Minimum and Maximum quantities +- Simple, Configurable (e.g. size, color, etc.), Bundled and Grouped Products +- Virtual Products +- Downloadable/Digital Products +- Available via customization: Customer Personalized Products – upload text for embroidery, monogramming, etc. +- Tax Rates per location, customer group and product type +- Attribute Sets for quick product creation of different item types +- Create Store-specific attributes on the fly +- Media Manager with automatic image resizing and watermarking +- Advanced Pricing Rules and support for Special Prices (see marketing tools) +- Available via customization: Customer Personalized Products – Upload Image +- Available via customization: Customer Personalized Products – Select Date/Time options for products + +### Product Browsing + +- Multiple Images Per Product +- Product Image Zoom-in Capability +- Related Products +- Stock Availability +- Product Option Selection +- Grouped Products View +- Add to Wishlist + +### Catalog Browsing + +- Ultrafast ElasticSearch full catalog support with Service Workers caching +- 100% Offline support +- Layered / Faceted Navigation for filtering of products in categories +- Recently viewed products +- Product comparisons +- Cross-sells, Up-sells and Related Items +- Available via customization: Product listing in grid or list format +- Breadcrumbs diff --git a/docs/guide/basics/modules.md b/docs/guide/basics/modules.md new file mode 100644 index 0000000000..0acc09d131 --- /dev/null +++ b/docs/guide/basics/modules.md @@ -0,0 +1,61 @@ +# Modules + +:::warning Important +Modules are under heavy development. Only a few parts of Vue Storefront are rewritten to modular architecture but we are aiming to rewrite everything soon along with adding TypeScript support and Unit tests to each of them. Some concepts may change over time before we introduce the final version of VS Modules. +::: + +## What are VS modules? + +You can think about each module as a one independent feature available in Vue Storefront with all its logic and dependencies inside. This 'one feature' however is a common denominator that links all the features inside. For example common denominator for adding product to the cart, receiving list of items that are in a cart or applying a cart coupon is obviously a `cart` and `cart` is not a feature of anything bigger than itself so it should be a module. Wishlist or Newsletter are also a good examples of modules as we intuitively think about them as a standalone features. If you still have troubles with understanding what exactly they are at this point, don't worry - you can find a better explanation below. + +## Motivation + +I believe that some neat metaphore can clearly describe the problem as well as a solution. + +To better illustrate the whole concept I'll try to explain it with lego bricks. + +Let's say we have a box with 90 lego bricks that we can use to build some fancy things like Towers, Castles, or Helicopters. Unfortunately due to some stupid EU regulations we can only have 3 different colors of bricks in our box. As we all know not every color is accurate for every structure that can be built so we need to swap one color with a different one from the shop from time to time to have bricks in colors that are best-suited for our next lego project. + +Cool, but there is one problem - since we have all our bricks in one box they look more or less like this: + + + +When we want to replace the green bricks with, let's say, the black ones we need to look for each green brick separately among all the others which can take a lot of time... and there is still a chance that we will miss some of them! Not to mention that finding the particular green brick that we need to finish the palm tree we are building ([this one!](https://www.thedailybrick.co.uk/media/catalog/product/cache/1/image/700x700/9df78eab33525d08d6e5fb8d27136e95/l/e/lego_small_palm_leaf_8_x_3__6148__lego-green-small-palm-leaf-8-x-3-6148-30-257873-61.jpg)) will require looking for it among all the other bricks which can make this task extremely difficult and time-consuming. + +This is obviously not a situation that we want to end up in with our small lego empire. Neither we want it with Vue Storefront since it's meant to be easily extendable so you can replace your green bricks (or current user cart feature) with the black ones (different cart feature with multiple carts) without looking for each of them among all the bricks and without worrying that you will miss some of them and EU will confiscate all the bricks you have! We also want to make it easier to find the exact brick we want right now to finish this damn palm tree! + +So how we make this horrible situation better? + +Introducing... (drums in the background) **_bricks grouped by colors_**! (wows in the background) + + + +When we have our bricks grouped by their colors (and in a separate boxes - modules) it's much easier to find this green brick that we needed for a palm tree since we only need to search in a small subset of all bricks. Moreover when we want to replace green bricks with the black ones then instead of looking for all the green representatives one by one we are just replacing their box with the one containing black bricks. We also don't need to worry that something was left since we know that all the green bricks were in the box. + +This is the kind of modularity and extendibility we want in Vue Storefront. If you think about each small feature (or user story) like signing in or adding product to a cart as a brick then we can group them by their common denominator which in case of bricks is a color but in case of user stories it can be some particular subset of data/features that we are interacting with (like a Cart, Acoount etc). + +## What is the purpose of VS modules? + +The purpose is well described in [this discussion](https://github.com/DivanteLtd/vue-storefront/issues/1213). It can be summarized to: + +- **Better extensibility**: We can extend each module or replace it completely with the new one. For example we may want to replace our Cart module with the one that allows to have multiple carts. With modules we can just detach current Cart module and replace it with our new one. Another example can be using different modules for different content CMS integration etc. +- **Better developer experience**: Along with the modules we are introducing many features focused on delivering better, easier to jump in and more predictable developer experience. We changed the way you can compose components with features, added unit tests, TypeScript interfaces etc. +- **Better upgradability**: Each module is a separate NPM package therefore can be upgraded independently and since it has all the logic encapsulated it shouldn't break any other parts of the application when detached, modified or replaced. + +## How module should look like + +Module by its definition should encapsulate all logic required for the feature it represents. You can think about each module as a micro application that exposes it's parts to the outside world (Vue Storefront). + +Normally module can (but not must) contain following folders: + +- `features` - Atomic, almost indivisible features related to this module that can be used to build your components. Each of this features can be treated as one user story. Examples of such features are: Adding product to the cart, signing in, signing out, removing product from the wishlist, getting products that are in a cart etc. We can use this features in components by importing the ones that we need from the module `import { addToCart, removeFromCart } from 'module/cart/features` +- `components` - components related to this module (eg. Microcart for Cart module) +- `store` - Vuex store associated to module +- `helpers` - everything else that is meant to support modules behavior +- `types` - TypeScript types associated with a module +- `test` - folder with unit tests which is _required_ for every new or rewritten module. This folder can be placed outside of the module in 'tests' folder. +- `extends` - code that you need to include into core files such as client/server entry, app entry, webpack config or service worker. If you need to extend, let's say `client-entry.js`, just create a file with the same name and import it in the core `client-entry.js` by invoking files content with `import core/module/module-name/extends/client-entry.js`. + +## Contributions + +Please introduce every new feature as a standalone, encapsulated module. We also need your help in rewriting Vue Storefront to modular approach - [here](https://github.com/DivanteLtd/vue-storefront/issues?q=is%3Aissue+is%3Aopen+label%3A%22API+Module%22) you can find tasks related to this architectural change and [here](https://github.com/DivanteLtd/vue-storefront/blob/master/doc/api-modules/refactoring-to-modules.md) is the tutorial how to approach applying this changes. diff --git a/docs/guide/basics/project-structure.md b/docs/guide/basics/project-structure.md new file mode 100644 index 0000000000..0373f53aa3 --- /dev/null +++ b/docs/guide/basics/project-structure.md @@ -0,0 +1,38 @@ +# Project structure + +## Using git for custom development + +One of the options is to do kind of a fork - or just to get the whole repo to your Git service. Then if you like to do some VS updates, you will probably need to just pull the changes from our origins. Another option will be available as soon as we manage to separate the core as a npm module + +## Structure details + +Below you can find the Vue Storefront project structure with explanations and corresponding docs. This is a good place to start with the project. + +- `config` - Config files for vue storefront. They're used to define backend addresses, current theme etc. + - `default.json` - Default config template which should never be changed. If you want to make some changes in config create `local.json` file in the same folder, copy the content and make changes here. Default `config.json` will be overwritten by `local.json` for your setup. + - `local.json` (optional) - your custom Vue Storefront config. You can find a detailed description of all config file properties in the [Vue Storefront configuration chapter](configuration.md). +- `docs` - Project documentation +- `core` - Vue Storefront core + :::warning + Don't modify `core` directory on your project if you want to receive core updates + ::: + + - `assets` - Global assets used in project like logo, app icons, placeholders and `manifest.json`, eventually will be removed and moved to themes. You can place your theme-specific assets in `{themeroot}/assets` + - `build` - It contains `config.json` generated from files in `/config` folder and webpack build. It's made from vue-cli webpack template. You can extend core webpack build in `{themeroot}/webpack.config.js` (related: [Working with Webpack](../core-themes/webpack.md)). + - `components` Vue Storefront core components (related: [Working with core components](../core-themes/core-components.md)) + - `filters` - Global Vue filters for the project. You can add your own filters in `{themeroot}/filters` + - `helpers` - Global methods for the project. + - `lib` - Core libraries allowing functionalities like theme support, extensions or filters + - `mixins` - Global mixins for the project. You can add your own mixins in `{themeroot}/mixins` + - `models` - Data models for things like orders or notifications, eventually will be moved to documentation + - `pages` - Vue Storefront core pages (related: [Working with core components](../core-themes/core-components.md)) + - `plugins` - Core plugins (related: [Working with plugins](../core-themes/plugins.md)) + - `resource` - Data mocks used to develop new features + - `router` - Core Vue Router setup. The definition of routes happens in `{themeroot}/index.js` + - `scripts` - Core scripts like app installer, extension installer etc. + - `service-worker` - Core service worker. It's merged with `sw-precache` data from `build` and `{theme}/service-worker-ext.js` + - `store` - Core Vuex stores (related: [Working with Vuex](../data/vuex.md), [Working with data](../core-themes/data.md)) + +- `src` - Main project folder containing Vue Storefront core and themes. This is your app playground so you can modify this folder. + - `extensions` - Custom extensions made for Vue Storefront like integration with MailChimp or support for Google Analytics) (see: [Working with extensions](../core-themes/extensions.md)) + - `themes` - Vue Storefront core themes. You can change the active theme in `config/` folder. (see: [Working with themes](../core-themes/themes.md)). diff --git a/docs/guide/basics/recipes.md b/docs/guide/basics/recipes.md new file mode 100644 index 0000000000..298ee42064 --- /dev/null +++ b/docs/guide/basics/recipes.md @@ -0,0 +1,256 @@ +# FAQ and Recipes + +Below you can find solutions for most common problems and advises for typical config changes required by Vue Storefront. +If you solved any new issues by yourself please let us know on [slack](http://vuestorefront.slack.com) and we will add them to the list so others don't need to reinvent the wheel. + +## Problem starting docker while installing the vue-storefront + +In case you get the following error: + +``` +┌────────────────────────────────────────────────────────────────────────────┐ +│ ERROR │ +│ │ +│ Can't start docker in background. │ +│ │ +│ Please check log file for details: /tmp/vue-storefront/var/log/install.log │ +└────────────────────────────────────────────────────────────────────────────┘ +``` + +Please check: + +- if there is `docker-compose` command available, if not please do install it; +- please check the output of running `docker-compose up -d` manually inside the `vue-storefront-api` instance. On some production environments docker is limited for the superusers, in many cases it's just a matter of `/var/run/docker.sock` permissions to be changed (for example to 755) + +## Product not displayed (illegal_argument_exception) + +In a case of + +```json +{ + "root_cause": [ + { + "type": "illegal_argument_exception", + "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [created_at] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead." + } + ], + "type": "search_phase_execution_exception", + "reason": "all shards failed", + "phase": "query", + "grouped": true, + "failed_shards": [ + { + "shard": 0, + "index": "vue_storefront_catalog_1521776807", + "node": "xIOeZW2lTwaprGXh6YLyCA", + "reason": { + "type": "illegal_argument_exception", + "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [created_at] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead." + } + } + ] +} +``` + +See the discussion in [#137](https://github.com/DivanteLtd/vue-storefront/issues/137). +Please also check the [Database tool](https://github.com/DivanteLtd/vue-storefront/blob/master/doc/Database%20tool.md) + +## What's the recommended way to use git on custom development + +One of the options is to do kind of fork - or just to get the whole repo to your Git service. +Then if you like to do some VS updates you probably need to just pull the changes from our origins. Another option will be available as soon as we manage to separate the core as a npm module + +## How to add custom configurable attributes to Product page + +Where can we add filters and extra configurable options for the products? For example, I've just added an iPhone X as an example. And I want to add the storage as an option. + +![How to add additional custom attribute?](/vue-storefront/Apple_iPhone_X.png) + +To do so, you need to modify the theme, changing the following snippet: + +```html +
+
+ +
+
+ +
+``` + +You must add UI controls for additional configurable attributes. + +## Product name changed to SKU when adding to cart / on product page + +By default, when the user selects any specific product variant on the `Product.vue` page for `configurable` products - the title, picture, price and other attributes are changed to corresponding `simple` one (within `product.configurable_children`). If in the Magento panel the product names of the variants are set to SKU or anything else, then the correct behavior is that the product name change to it when selects variant. + +To correct this behavior you can: + +- modify the [core](https://github.com/DivanteLtd/vue-storefront/blob/6a5a569a7e96703b865f841dabbe3c6a1020b3ab/core/store/modules/product/actions.js#L311) - to filter out the `name` attribute from `Object.assign` which is responsible for copying the attributes from variant -> current product, +- modify `mage2vuestorefront` importer to correct the `configurable_children` [product names](https://github.com/DivanteLtd/mage2vuestorefront/blob/ca0c4723530b148cfdfb99784168af529e39d599/src/adapters/magento/product.js#L167) +- or just use bound to the `EventBus.$emitFilter('product-after-single', { key: key, options: options, product: products[0] })` event and modify the `product.configurable_children` properties: + +```js + if (product.configurable_children) { + for (let configurableChild of product.configurable_children) { + configurableChild.name = product.name + } + } + } +``` + +## How to get dynamic prices to work (catalog rules) + +After following the Tutorial on [how to connect to Magento2](../installation/magento.md) the prices are updated just after manually running [mage2vuestorefront cli command](https://github.com/DivanteLtd/mage2vuestorefront). + +However there is an option to get the prices dynamically. To do so you must change the config inside `conf/local.json` from the default (`conf/default.json`): + +```json + "products": { + "preventConfigurableChildrenDirectAccess": true, + "alwaysSyncPlatformPricesOver": false, + "clearPricesBeforePlatformSync": false, + "waitForPlatformSync": false, + "endpoint": "http://localhost:8080/api/product" + }, +``` + +to: + +```json + "products": { + "preventConfigurableChildrenDirectAccess": true, + "alwaysSyncPlatformPricesOver": true, + "clearPricesBeforePlatformSync": true, + "waitForPlatformSync": false, + "endpoint": "http://localhost:8080/api/product" + }, +``` + +To make it work you need have Magento2 oauth keys configured in your `vue-storefront-api` - `conf/local.json`. +This change means that each time product list will be displayed, VS will get fresh prices directly from Magento without the need to re-index ElasticSearch. + +## No products found! after node --harmony cli.js fullreindex + +Take a look at the discussion at [#644](https://github.com/DivanteLtd/vue-storefront/issues/644) +Long story short -> you need to run the following command within the `mage2nosql` project: + +```bash +node cli.js products --partitions=1 +``` + +## How to sync the products cart with Magento to get the Cart Promo Rules up and running + +To display the proper prices and totals after Magento calculates all the discounts and taxes you need to modify the `conf/local.json` config (for a reference take a look at `conf/default.json`) by putting there an additional section: + +```json + "cart": { + "synchronize": true, + "synchronize_totals": true, + "create_endpoint": "http://localhost:8080/api/cart/create?token={{token}}", + "updateitem_endpoint": "http://localhost:8080/api/cart/update?token={{token}}&cartId={{cartId}}", + "deleteitem_endpoint": "http://localhost:8080/api/cart/delete?token={{token}}&cartId={{cartId}}", + "pull_endpoint": "http://localhost:8080/api/cart/pull?token={{token}}&cartId={{cartId}}", + "totals_endpoint": "http://localhost:8080/api/cart/totals?token={{token}}&cartId={{cartId}}" + }, +``` + +To make it work you need have Magento2 oauth keys configured in your `vue-storefront-api` - `conf/local.json`. + +After this change you need to restart the `yarn dev` command to take the config changes into consideration by the VS. All the cart actions (add to cart, remove from cart, modify the qty) are now synchronized directly with Magento2 - for both: guest and logged in clients. + +## How to prevent an error "Can’t build storefront npm" + +The error "Can't build storefront npm" appears because npm can't automatically install required modules. To prevent this error, you should manually install those modules before running the installer. It's easy: + +```bash +git clone https://github.com/DivanteLtd/vue-storefront.git vue-storefront && cd vue-storefront +npm install +npm install vue-carousel vue-no-ssr +npm run build # check if no errors +npm run installer +``` + +## How to integrate 3rd party platform? Do you think it could be used with a legacy bespoke PHP eCommerce? + +Yes I believe it could. You should expose the API accordingly to our [spec](../extensions/extending-api.md) and the second step is to [create a data bridge](https://medium.com/@piotrkarwatka/how-to-connect-3rd-party-platform-to-vue-storefront-df9cb30779f6) to fill out the ElasticSearch with the current catalog data. + +## Is there any documentation on integrating payment gateways? + +We're working on kind of boilerplate for payment modules. Right now please just take a look at a [live example](https://github.com/develodesign/vue-storefront-stripe) and try to follow the design patterns from there. The task where boilerplate + docs will show up is: [https://github.com/DivanteLtd/vue-storefront/issues/923](https://github.com/DivanteLtd/vue-storefront/issues/923). + +## Is there any internationalization support? + +Yes, we already have 7 languages supported by default (EN, FR, ES, RU, JP, NL, DE) and the [documentation for translations](../core-themes/translations.md). + +The currency is set in the `local.json` configuration file and it's (along with the language) set per instance - so if you have a few languages and countries supported you need to run (as for now) a few separate instances + +## If 10k products are on the site will it create a high bandwidth download when you navigate on the site for the first time on a mobile device + +Not necessarily. Vue Storefront is caching products from the categories browsed. This is default solution which can be changed by modifying `core/store/lib/search.js` + +## How to add/remove/change field types in the ElasticSearch schema + +It's done via Database Tool schema changes. Please follow the instructions from the [Database Tool Manual](../data/database-tool.md#chaning-the-index-structure--adding-new-fields--chaning-the-types). + +## How to integrate 3rd party Magento extensions + +Unfortunately, Magento extensions are not compliant with any PWA available solution yet. So if you would like to integrate some existing extensions, the simplest way is to: + +- expose the data via some Magento2 REST api endpoints; +- consume the endpoints in the VS using Vuex stores; [read more](../data/vuex.md) about Vuex in Vue Storefront; +- implement the UI in VS + +If the extensions are not playing with the User Interface, probably they will work with VS out of the box, as we're using the standard Magento2 API calls for the integration part. + +## How to support Multistore / Multiwebsite setup + +Please check the [Multistore setup](../integrations/multistore.md) guide for details + +## How to deal with Category filters based on configurable_children + +If you would like to have a Category filter working with configurable products, you need to expand the `product.configurable_children.attrName` to `product.attrName_options` array. This is automatically done by [mage2vuestorefront](https://github.com/DivanteLtd/mage2vuestorefront) for all attributes set as `product.configurable_options` (by default: color, size). If you like to add additional fields like `manufacturer` to the filters, you need to expand `product.manufacturer_options` field. The easiest way to do so is to set `config.product.expandConfigurableFilters` to `['manufacturer']` and re-run the `mage2vuestorefront` indexer. + +## How to redirect original Magento2 urls to Vue Storefront + +There is a SEO redirects generator for nginx -> `https://serverfault.com/a/441517` available within the [vue-storefront-api](https://github.com/DivanteLtd/vue-storefront-api/commit/2c7e10b4c4294f222f7a1aae96627d6a0e23f30e). Now you can generate SEO map redirecting users from the original Magento urls to Vue Storefront URLs by running: + +```bash +npm run seo redirects — —oldFormat=true | false +``` + +- `oldFormat` - should be set accordingly to the `vue-storefront/config/local.json` setting of `products.useShortCatalogUrls` (`oldFormat` = `!useShortCatalogUrls`) + +Please make sure that `vue-storefront/config/local.json` setting of `useMagentoUrlKeys` is set to `true` and you have ElasticSearch synchronized with the Magento2 instance using current version of [mage2vuestorefront](https://github.com/DivanteLtd/mage2vuestorefront). + +## You need to choose options for your item message when hit API for add to cart a configurable product + +This is because the demo data dump works on the `demo-magento2.vuestorefront.io` instance attribute ids. Please re-import all product data using [mage2vuestorefront](https://github.com/DivanteLtd/mage2vuestorefront) + +## Adding custom category filters + +You need to add the attributes you'll like to have displayed to the `config/local.json` field name is: `products.defaultFilters`: + +```json +"defaultFilters": ["color", "size", "price", "erin_recommends"], +``` + +And then You can use proper controls for each individual filter [here](https://github.com/DivanteLtd/vue-storefront/blob/49dc8a2dc9326e9e83d663cc27f8bb0688525f13/src/themes/default/components/core/blocks/Category/Sidebar.vue). diff --git a/docs/guide/basics/typescript.md b/docs/guide/basics/typescript.md new file mode 100644 index 0000000000..53d3c9b769 --- /dev/null +++ b/docs/guide/basics/typescript.md @@ -0,0 +1,34 @@ +# TypeScript Action Plan + +We've started adding the TypeScript support to Vue Storefront - mostly because of the following reasons: + +- developer convenience (intellisense support in the IDEs) +- types safety and code-testability +- making Vue Storefront code base easier to understand for newcomers. + +## Desired state + +**Type Script is for internal implementation only. Does NOT affect ES users, but should improve TS integration for TS users.** + +Desired state is that Vue Storefront Core outputs JS libraries, it's written using some TypeScript features, but all the user code (themes, extensions) is still JavaScript. No TypeScript experience is required to build Vue Storefront stores. **This is just for core developers and transparent to the end users.** + +Therefore we're refactoring just: + +- core/api +- core/store +- core/lib + +where it makes sense. The key TypeScript feature we feel is usable are data types. + +We're in the middle of [refactoring `core/components` to `core/api` modules](https://github.com/DivanteLtd/vue-storefront/issues/1213). All the modules should be created using TypeScript + +### The Action Plan: + +1. Introduce types - move _.js modules to _.ts modules incrementally without breaking changes. +2. Use types when it's appropriate in your newly written modules and new features. +3. One Vuex module, or just few components refactored within one release (once a month) is fine. +4. All `core/api` modules should be created using TypeScript. +5. All new modules and Vuex stores should be created using TypeScript. +6. **For now please don't refactor existing UI layer (components, pages) to use TypeScript. We should focus at Vuex, core libraries and APIs at first to not introduce a chaos into theme development.** +7. We should put the types/interfaces inside `core/store/types` for all Entity/Data related models or in `core/types` for some shared ones; for example: `Product.ts` should be placed in `core/store/types/product/Product.ts` +8. We should use minimal possible set of interfaces. Try to introduce 1-2 interfaces per entity (e.g. Product shouldn't be represented by more than 2 interfaces) diff --git a/docs/guide/core-themes/core-components.md b/docs/guide/core-themes/core-components.md new file mode 100644 index 0000000000..5fa744b1f8 --- /dev/null +++ b/docs/guide/core-themes/core-components.md @@ -0,0 +1,3 @@ +# Vue Storefront component types + +_Work in progress_ diff --git a/docs/guide/core-themes/data.md b/docs/guide/core-themes/data.md new file mode 100644 index 0000000000..931e933b6a --- /dev/null +++ b/docs/guide/core-themes/data.md @@ -0,0 +1,3 @@ +# Working with data + +_Work in progress_ diff --git a/docs/guide/core-themes/extensions.md b/docs/guide/core-themes/extensions.md new file mode 100644 index 0000000000..5426fa03ca --- /dev/null +++ b/docs/guide/core-themes/extensions.md @@ -0,0 +1,3 @@ +# Working with extensions + +_Work in progress_ diff --git a/docs/guide/core-themes/plugins.md b/docs/guide/core-themes/plugins.md new file mode 100644 index 0000000000..5c9f14bb42 --- /dev/null +++ b/docs/guide/core-themes/plugins.md @@ -0,0 +1,3 @@ +# Working with plugins + +_Work in progress_ diff --git a/docs/guide/core-themes/themes.md b/docs/guide/core-themes/themes.md new file mode 100644 index 0000000000..115f6064f3 --- /dev/null +++ b/docs/guide/core-themes/themes.md @@ -0,0 +1,3 @@ +# Themes in Vue Storefront + +_Work in progress_ diff --git a/docs/guide/core-themes/translations.md b/docs/guide/core-themes/translations.md new file mode 100644 index 0000000000..32c8c1cc43 --- /dev/null +++ b/docs/guide/core-themes/translations.md @@ -0,0 +1,54 @@ +# Internationalization (i18n) of Vue Storefront + +Vue Storefront allows you to translate the whole UI using powerful [vue-i18n](http://kazupon.github.io/vue-i18n/api/#methods) library. + +Please be aware of i18n issues while writing your own themes/extensions and keep the i18n support in mind, especially when creating Pull Requests to the core + +## Using i18n in code + +When you're working with plain JS module you can simply use the translation helper: + +```js +import i18n from '@vue-storefront/i18n'; +EventBus.$emit('notification', { + type: 'success', + message: i18n.t('Product has been added to the cart!'), + action1: { label: i18n.t('OK'), action: 'close' }, +}); +``` + +If you're working with \*.vue components the matter is even simpler with Vue directive `$t`: + +```html + + {{ $t('Size guide') }} + +``` + +For all helper methods and directives along with available parameters please do check the [vue-i18n documentation](http://kazupon.github.io/vue-i18n/api/#methods). + +## Working with translations + +Translations are provided in `resource/i18n/en-US.csv` file and can be extended / overriden in `theme/resource/i18n/en-US.csv` accordingly. + +Here's an example of `en-US.csv` for `en-US` locale: + +```csv +"customMessage","You can define or override translation messages here." +"welcomeMessage", "Welcome to Vue Storefront theme starter!", +"In case of any problems please take a look at the docs. If you havn't find what you were looking for in docs feel free to ask your question on our Slack", "In case of any problems please take a look at the docs. If you havn't find what you were looking for in docs feel free to ask your question on our Slack", +"Here are some links that can help you with developing your own theme", "Here are some links that can help you with developing your own theme", +"Project structure", "Project structure", +"Working with themes", "Working with themes", +"Working with components", "Working with components", +"Working with data", "Working with data", +"Vue Storefront Logo", "Vue Storefront Logo" +``` + +when you create the `en-US.csv` file within your `theme/resource/i18n/` folder and override some messages like: + +```csv +"customMessage","You can define or override translation messages here." +``` + +... you may expect that `$t('customMessage)` will return `You can define or override translation messages here.` instead of `Here is the core message. that can be overwritten in the theme`. As simple as that! :) diff --git a/docs/guide/core-themes/webpack.md b/docs/guide/core-themes/webpack.md new file mode 100644 index 0000000000..25425c0260 --- /dev/null +++ b/docs/guide/core-themes/webpack.md @@ -0,0 +1,3 @@ +# Working with Webpack + +_Work in progress_ diff --git a/docs/guide/data/data.md b/docs/guide/data/data.md new file mode 100644 index 0000000000..566882f8f1 --- /dev/null +++ b/docs/guide/data/data.md @@ -0,0 +1,3 @@ +# Data + +_Work in progress_ diff --git a/docs/guide/data/database-tool.md b/docs/guide/data/database-tool.md new file mode 100644 index 0000000000..aed420caa4 --- /dev/null +++ b/docs/guide/data/database-tool.md @@ -0,0 +1,58 @@ +# Database tool + +Vue Storefront gets it's all data from [vue-storefront-api](https://github.com/DivanteLtd/vue-storefront-api) endpoints, operating on top of Elastic Search data store. + +If You installed the project using `npm run installer` command then, the database has been set up, data imported from demo-dump and everything should be just fine. +After some more extensive data operations - like custom imports using [mage2vuestorefront](https://github.com/DivanteLtd/mage2vuestorefront) or [magento1-vsbridge](https://github.com/DivanteLtd/magento1-vsbridge) there is a need to re-index the ElasticSearch and setup the proper metadata for fields. + +The main reason You know You must reindex the database is kind of the following error You get from vue-storefront console: + +```json +Error: {"root_cause":[{"type":"illegal_argument_exception","reason":"Fielddata is disabled on text fields by default. Set fielddata=true on [created_at] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"vue_storefront_catalog_1521776807","node":"xIOeZW2lTwaprGXh6YLyCA","reason":{"type":"illegal_argument_exception","reason":"Fielddata is disabled on text fields by default. Set fielddata=true on [created_at] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."}}]} +``` + +In this case there is a db tool inside your local `vue-storefront-api` installation to the rescue. + +## Re-indexing existing database + +Please go to `vue-storefront-api` directory and run: +`npm run db rebuild` + +This command will: + +- reindex your currently set (in the `config/local.json` config file) elastic search index to temp-one, +- put the right elastic search mappings on top of the temp index, +- drop the original index, +- create the alias with original name to the temp one - so You can use original name without any reference chcanges. + +You can specify different (than this set in `config/local.json`) index name by running: +`npm run db rebuild -- --indexName=custom_index_name` + +## Creating the new index + +If you like to create new, empty index please run: +`npm run db new` + +This tool will drop your current index and create new, empty one with all the metafields set. + +You can specify different (than this set in `config/local.json`) index name by running: +`npm run db rebuild -- --indexName=custom_index_name` + +## Chaning the index structure / adding new fields / chaning the types + +If You like to extenend the ElasticSearch data structures or map some particular field types. For example after getting kind of this error: + +``` +[{"type":"illegal_argument_exception","reason":"Fielddata is disabled on text fields by default. Set fielddata=true on [created_at] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."}] +``` + +Please do change the ES schema by modifying: + +- [config/elastic.schema.product.extension.json](https://github.com/DivanteLtd/vue-storefront-api/blob/master/config/elastic.schema.product.extension.json) +- [config/elastic.schema.attribute.extension.json](https://github.com/DivanteLtd/vue-storefront-api/blob/master/config/elastic.schema.attribute.extension.json) +- [config/elastic.schema.taxrate.extension.json](https://github.com/DivanteLtd/vue-storefront-api/blob/master/config/elastic.schema.taxrate.extension.json) + +The format is compliant with ES DSL for schema modifications: https://www.elastic.co/blog/found-elasticsearch-mapping-introduction + +After the changes please do run the following indexing command: +`npm run db rebuild` diff --git a/docs/guide/data/ssr-cache.md b/docs/guide/data/ssr-cache.md new file mode 100644 index 0000000000..238ef5f9d0 --- /dev/null +++ b/docs/guide/data/ssr-cache.md @@ -0,0 +1,102 @@ +# SSR Cache + +Vue Storefront generates the Server Side rendered pages to improve the SEO results. In the latest version of Vue Storefront we've added the Output cache option (disabled by default) to improve the performance. + +The output cache is set by the following `config/local.json` variables: + +```json + "server": { + "host": "localhost", + "port": 3000, + "protocol": "http", + "api": "api", + "useOutputCacheTagging": true, + "useOutputCache": true, + "outputCacheDefaultTtl": 86400 + }, + "redis": { + "host": "localhost", + "port": 6379, + "db": 0 + }, +``` + +## Dynamic tags + +The dynamic tags config uption: `useOutputCacheTaging` - if set to true, Vue Storefront is generating the special HTTP Header `X-VS-Cache-Tags` + +```js +res.setHeader('X-VS-Cache-Tags', cacheTags); +``` + +Cache tags are assigned regarding the products and categories which are used on the specific page. Typical `X-VS-Cache-Tags` tag looks like this: + +``` +X-VS-Cache-Tags: P1852 P198 C20 +``` + +The tags can be used to invalidate the Varnish cache if You're using it. [Read more on that](https://www.drupal.org/docs/8/api/cache-api/cache-tags-varnish). + +## Redis + +If both `useOutputCache` and `useOutputCacheTagging` options are set to `true` - Vue Storefront is using Output Cache stored in Redis (configured in the `redis` section of the config file). Cache is tagged with Dynamic tags and can be invalidated using special webhook: + +Example call to clear all pages containing specific product and category: +`curl http://localhost:3000/invalidate?tag=P1852,C20` + +Example call to clear all product, category and home pages: +`curl http://localhost:3000/invalidate?tag=product,category,home` + +**WARNING:** +We strongly recommend You to NOT USE Output cache in the development mode. By using it You won't be able to refresh the UI changes after modyfing the Vue components etc. + +## CLI cache clear + +You can manualy clear Redis cache for specific tags by running the following command: + +```bash +npm run cache clear +npm run cache clear -- --tag=product,category +npm run cache clear -- --tag=P198 +npm run cache clear -- --tag=* +``` + +Available tag keys are set in the `config.server.availableCacheTags` (by default: `"product", "category", "home", "checkout", "page-not-found", "compare", "my-account", "P", "C"`) + +**Dynamic cache invalidation:** Recent version of [mage2vuestorefront](https://github.com/DivanteLtd/mage2vuestorefront) do support output cache invalidation. Output cache is being tagged with the product and categories id (products and categories used on specific page). Mage2vuestorefront can invalidate cache of product and category pages if You set the following ENV variables: + +```bash +export VS_INVALIDATE_CACHE_URL=http://localhost:3000/invalidate?key=SECRETKEY&tag= +export VS_INVALIDATE_CACHE=1 +``` + +**SECURITY NOTE:** Please note that `key=SECRETKEY` should be equal to `vue-storefront/config/local.json` value of `server.invalidateCacheKey` + +## Adding new types / cache tags + +If You're adding new type of page (`core/pages`) and `config.server.useOutputCache=true` - You should also extend the `config.server.availableCacheTags` of new general purpose tag that will be connected with the URLs connected with this new page. + +After doing so, please add the `asyncData` method to Your page code assigning the right tag (please take a look at `core/pages/Home.js` for instance): + +```js + asyncData ({ store, route }) { // this is for SSR purposes to prefetch data + return new Promise((resolve, reject) => { + store.state.requestContext.outputCacheTags.add(`home`) + console.log('Entering asyncData for Home root ' + new Date()) + EventBus.$emitFilter('home-after-load', { store: store, route: route }).then((results) => { + return resolve() + }).catch((err) => { + console.error(err) + reject(err) + }) + }) + }, +``` + +This line: + +```js +store.state.requestContext.outputCacheTags.add(`home`); +``` + +... is in charge of assigning the specific tag with current HTTP request output. diff --git a/docs/guide/data/vuex.md b/docs/guide/data/vuex.md new file mode 100644 index 0000000000..342630fe56 --- /dev/null +++ b/docs/guide/data/vuex.md @@ -0,0 +1,3 @@ +# Working with Vuex + +_Work in progress_ diff --git a/docs/guide/extensions/README.md b/docs/guide/extensions/README.md new file mode 100644 index 0000000000..867ff4bc0c --- /dev/null +++ b/docs/guide/extensions/README.md @@ -0,0 +1,3 @@ +# Extensions + +_Work in progress_ diff --git a/docs/guide/extensions/extending-api.md b/docs/guide/extensions/extending-api.md new file mode 100644 index 0000000000..415b713e30 --- /dev/null +++ b/docs/guide/extensions/extending-api.md @@ -0,0 +1,102 @@ +## Extending the API + +Some extensions need to have additional API methods to get some data directly from Magento/other CMS or just from custom ElasticSearch data collections. +You may add new ES collections [using the Migration mechanism](https://github.com/DivanteLtd/vue-storefront-api/blob/master/doc/1.%20Data%20schema%20and%20migrations.md) + +Then You may extend the [`vue-storefront-api`](https://github.com/DivanteLtd/vue-storefront-api) to add Your custom API methods. Please take a look at: [mailchimp-subscribe](https://github.com/DivanteLtd/vue-storefront-api/blob/master/src/api/extensions/mailchimp-subscribe/index.js) for reference. + +To add the API extension to `vue-storefront-api`: + +1. Create the folder within `src/api/extensions` for example 'custom_extension` +2. Then add the `index.js` file and put the API methods code inside. We're using Express.js. Here is a boilerplate/example for the extension code: + +```js +import { apiStatus } from '../../../lib/util'; +import { Router } from 'express'; + +module.exports = ({ config, db }) => { + let mcApi = Router(); + + /** + * POST create an user + */ + mcApi.post('/subscribe', (req, res) => { + let userData = req.body; + if (!userData.email) { + apiStatus(res, 'Invalid e-mail provided!', 500); + return; + } + + let request = require('request'); + request( + { + url: + config.extensions.mailchimp.apiUrl + + '/lists/' + + encodeURIComponent(config.extensions.mailchimp.listId) + + '/members', + method: 'POST', + headers: { + Authorization: 'apikey ' + config.extensions.mailchimp.apiKey, + }, + json: true, + body: { email_address: userData.email, status: 'subscribed' }, + }, + function(error, response, body) { + if (error) { + apiStatus(res, error, 500); + } else { + apiStatus(res, body, 200); + } + }, + ); + }); + + /** + * DELETE delete an user + */ + mcApi.delete('/subscribe', (req, res) => { + let userData = req.body; + if (!userData.email) { + apiStatus(res, 'Invalid e-mail provided!', 500); + return; + } + + let request = require('request'); + request( + { + url: + config.extensions.mailchimp.apiUrl + + '/lists/' + + encodeURIComponent(config.extensions.mailchimp.listId), + method: 'POST', + headers: { + Authorization: 'apikey ' + config.extensions.mailchimp.apiKey, + }, + json: true, + body: { + members: [{ email_address: userData.email, status: 'unsubscribed' }], + update_existing: true, + }, + }, + function(error, response, body) { + if (error) { + apiStatus(res, error, 500); + } else { + apiStatus(res, body, 200); + } + }, + ); + }); + return mcApi; +}; +``` + +3. Add the extension to `config/local.json`: + +```json + "registeredExtensions": ["mailchimp-subscribe"], +``` + +4. Restart the `vue-storefront-api` +5. Your new API method is available on `localhost:8080/api/ext//` for example: `localhost:8080/api/ext/mailchimp-subscribe/subscribe` diff --git a/docs/guide/installation/linux-mac.md b/docs/guide/installation/linux-mac.md new file mode 100644 index 0000000000..c6b4ffc764 --- /dev/null +++ b/docs/guide/installation/linux-mac.md @@ -0,0 +1,207 @@ +# Installing on Linux/MacOS + +The steps below are tested on MacOS and Linux environments. If you're on Windows please check [Windows Installation Tutorial](windows.md). + +Let's go! + +## Requirements + +- Docker (with [docker-compose](https://docs.docker.com/compose/install/) installed). + + Already included in `vue-storefront` and `vue-storefront-api` Docker images (required locally, if you do not use containerization): + +- Node.js [Active LTS](https://nodejs.org/en/) (>=8.0.0) +- [Yarn](https://yarnpkg.com/en/docs/install) (>=1.0.0) +- [ImageMagick](https://www.imagemagick.org/script/index.php) (to fit, resize and crop images) + +## User-friendly installation + +If you're MacOS or Linux user now you're able to install with pretty nice CLI installer :) + +```bash +git clone https://github.com/DivanteLtd/vue-storefront.git vue-storefront +cd vue-storefront +yarn +yarn installer +``` + +It will take some time for installation and during the last step you will be asked some questions. First one is + +``` +Would you like to use https://demo.vuestorefront.io as the backend? +``` + +If you answer `Yes`, you will have remote backend at `https://demo.vuestorefront.io`. Otherwise, you will need to install `vue-storefront-api`. + +### Using Vue Storefront demo as a backend + +In this case you don't need to run Docker and you will be asked one additional question: + +``` +? Please provide path for images endpoint (https://demo.vuestorefront.io/img/) +``` + +You can simply proceed and as a result you will have a `vue-storefront` folder inside your project root and Storefront application running on `http://localhost:3000`. All images will be also hosted at `https://demo.vuestorefront.io/img/`. + +### Installing the vue-storefront-api locally + +If you answer `No` on the previous question, please be sure the Docker is running, otherwise you might get an error. You will be asked some more questions immediately: + +``` +? Would you like to use https://demo.vuestorefront.io as the backend? No +? Please provide Git path (if it's not globally installed) git +? Please provide path for installing backend locally ../vue-storefront-api +? Choose path for images endpoint http://localhost:8080/img/ +``` + +As for images endpoint: you can choose between `https://demo.vuestorefront.io/img/` again or host your images on localhost. + +After you answered all the questions, the installation process will start (it might take some time to install all dependencies). When it's finished, you will get the following message: + +``` +┌────────────────────────────────────────────────────────────────┐ +│ Congratulations! │ +│ │ +│ You've just successfully installed vue-storefront. │ +│ All required servers are running in background │ +│ │ +│ Storefront: http://localhost:3000 │ +│ Backend: http://localhost:8080 │ +│ │ +│ Logs: /Users/natalia/Desktop/work/test/vue-storefront/var/log/ │ +│ │ +│ Good Luck! │ +└────────────────────────────────────────────────────────────────┘ +``` + +Your project should contain 2 folders at this moment: `vue-storefront` and `vue-storefront-api`. Vue Storefront should be running on `http://localhost:3000`: + +![Storefront screenshot](/vue-storefront/storefront.png) + +## Manual installation + +### Install the vue-storefront-api + +You need to use [https://github.com/DivanteLtd/vue-storefront-api](https://github.com/DivanteLtd/vue-storefront-api). It's the ultimate API backend for this application. + +```bash +git clone https://github.com/DivanteLtd/vue-storefront-api.git vue-storefront-api +cd vue-storefront-api +``` + +You can choose between two modes of running the application: + +1. The **legacy** mode - starting just Elastic and Redis containers: + + ```bash + docker-compose up -d + ``` + +2. The **standard** mode - starting Elastic, Redis and Vue Storefront API containers: + + ```bash + docker-compose -f docker-compose.yml -f docker-compose.nodejs.yml up -d + ``` + +If you choose to use **legacy** mode, you must manually install the Yarn dependencies for the project: + +```bash +yarn install +``` + +As a result, all necessary services will be launched: + +- Vue Storefront API runtime environment (Node.js with dependencies from `package.json`) +- [ElasticSearch](https://www.elastic.co/products/elasticsearch) +- [Redis](https://redis.io/) +- Kibana (optional) + +To test out the application you'll need some test data. In `vue-storefront-api/var/catalog.json` you have data dump for ElasticSearch with default Magento2 products database. We're using for development purposes. + +First step is to configure the application: + +```bash +cp config/default.json config/local.json +nano config/local.json +``` + +The config file is quite simple, but here you have some comments: [Config file for vue-storefront](https://github.com/DivanteLtd/vue-storefront/wiki/Config-file-format-for-vue-storefront). + +:::tip NOTE +We're using powerful node.js library for config files, check the docs to learn more on it: [https://github.com/lorenwest/node-config](https://github.com/lorenwest/node-config). +::: + +To import these products we'll use `elasticdump` - which is provided by default with `package.json` dependencies and yarn command. Then, we need to update the structures in the database to the latest version (data migrations). + +Depending on the selected mode, execute the following commands: + +- **legacy** mode: + ```bash + yarn restore + yarn migrate + ``` +- **standard** mode: + ```bash + docker exec -it vue-storefront-api_app_1 yarn restore + docker exec -it vue-storefront-api_app_1 yarn migrate + ``` + +Clone the image files for default product database (we're using [Magento2 example products dataset](https://github.com/magento/magento2-sample-data). Please execute the following command in **the root folder of vue-storefront-api project**: + +```bash +git clone https://github.com/magento/magento2-sample-data.git var/magento2-sample-data +``` + +If you choose to use **standard** mode, the application is already running in the background. However, if you decided to stay with the **legacy** mode, you must start the application manually using following command (development mode with dynamic file reloads when changed): + +```bash +yarn dev +``` + +After all these steps you should be able to use the API application! + +You can check if everything works just fine by executing the following command: + +```bash +curl -i http://localhost:8080/api/catalog/vue_storefront_catalog/product/_search?q=bag&size=50&from=0 +``` + +Now, it's the time to install the frontend itself. + +### Install the vue-storefront + +First step is to clone [vue-storefront](https://github.com/DivanteLtd/vue-storefront) + +```bash +git clone https://github.com/DivanteLtd/vue-storefront.git vue-storefront +cd vue-storefront +``` + +Next, you have to prepare the config + +```bash +cp config/default.json config/local.json +nano config/local.json +``` + +The default config file should work perfectly fine for default purposes. + +Finally, you have to choose between two modes of running the application (similarly as in the case of vue-storefront-api). + +:::warning +If you choose the **legacy** mode, be sure to run `yarn install` first! +::: + +1. The **legacy** mode: + + ```bash + yarn build + yarn dev + ``` + +2. The **standard** mode (whole runtime environment inside the container): + ```bash + docker-compose up + ``` + +That's all - your frontend application is now up and running! You can check it on `localhost:3000` diff --git a/docs/guide/installation/magento.md b/docs/guide/installation/magento.md new file mode 100644 index 0000000000..09490cb394 --- /dev/null +++ b/docs/guide/installation/magento.md @@ -0,0 +1,132 @@ +# Integration with Magento 2 + +## Integrating Magento2 with your local instance + +As a first step, you need to to install [mage2vuestorefront ](https://github.com/DivanteLtd/mage2vuestorefront): + +```bash +git clone https://github.com/DivanteLtd/mage2vuestorefront.git mage2vs +cd mage2vs/src +yarn install +``` + +The tool is using Magento2 API via OAuth authorization, so you need to prepare Magento Integration access at first. Go to your Magento2 admin panel and click: _System -> Integrations_ + +![Magento Admin Panel](/vue-storefront/magento_1.png) + +Then click _Add new integration_ and just fill: + +- name (whatever) +- your password to confirm the changes, +- check Catalog, Sales, My Account and Carts on API permissions tab — save + +![Magento API](/vue-storefront/magento_2.png) + +In the result you’ll click _Activate_ and get some oauth access tokens: + +![Magento tokens](/vue-storefront/magento_3.png) + +Now please edit the `src/config.js` file in your `mage2vuestorefront` directory to set the following section: + +```js +magento: { + url: process.env.MAGENTO_URL || "http://your-magento-url.com/rest/", <- change to your Magento 2 URL, + consumerKey: process.env.MAGENTO_CONSUMER_KEY || 'alva6h6hku9qxrpfe02c2jalopx7od1q', + consumerSecret: process.env.MAGENTO_CONSUMER_SECRET || '9tgfpgoojlx9tfy21b8kw7ssfu2aynpm', + accessToken: process.env.MAGENTO_ACCESS_TOKEN || 'rw5w0si9imbu45h3m9hkyrfr4gjina8q', + accessTokenSecret: process.env.MAGENTO_ACCESS_TOKEN_SECRET || '00y9dl4vpxgcef3gn5mntbxtylowjcc9', +}, +``` + +As you can see, you can override the defaults by ENV variables as well. + +The rest of config.js entries points out to your `vue-storefront-api` based Docker and Redis instances which are required by `mage2nosql` to work. + +To import all the Products, Categories and other important stuff to your Elastic Search instance you should run the following commands (the sequence of commands is important  -  as for example `node cli.js categories` populates Redis cache for the further use of `node cli.js` products and so on) + +```bash +node cli.js taxrule +node cli.js attributes +node cli.js categories +node cli.js productcategories +node cli.js products +``` + +It’s safe to run these commands over and over as they’re doing `upsert` operation  - so inserts or updates the existing records. + +`cli.js` has a lot of other modes to be run in. Dynamic changes, queue support etc. You may experiment with them, but remember  -  the basic sequence for syncing the whole Magento2 database is like just shown. + +## Synchronizing orders and Magento images + +As you should have the products and categories already synchronized you may want to send some orders back to Magento or synchronize the shopping carts in the real time. + +`vue-storefront-api` is responsible for this write access to Magento. You may want just edit your `conf/local.json` within `vue-storefront-api` directory to set the OAuth Magento API access (`magento2` section): + +```json +"magento2": { + "url": "http://your-magento-url.com", + "imgUrl": "http://your-magento-url.com/media/catalog/product", + "assetPath": "/../var/magento2-sample-data/pub/media", + "api": { + "url": "http://your-magento-url.com/rest/", + "consumerKey": "alva6h6hku9qxrpfe02c2jalopx7od1q", + "consumerSecret": "9tgfpgoojlx9tfy21b8kw7ssfu2aynpm", + "accessToken": "rw5w0si9imbu45h3m9hkyrfr4gjina8q", + "accessTokenSecret": "00y9dl4vpxgcef3gn5mntbxtylowjcc9" + } +}, +``` + +To allow `vue-storefront-api` to resize your Magento’s images, please edit the `imgUrl` property under `magento2` section and add your Magento’s domain to `imageable` -> `whitelist`. + +```json +"imageable": { + "namespace": "", + "maxListeners": 512, + "imageSizeLimit": 1024, + "timeouts": { + "convert": 15000, + "identify": 300, + "download": 5000 + }, + "whitelist": { + "allowedHosts": [ + ".*your-magento-url.com", + ".*divante.pl", + ".*vuestorefront.io", + "localhost" + ], + "trustedHosts": [ + ".*your-magento-url.com", + ".*divante.pl", + ".*vuestorefront.io", + "localhost" + ] + }, +``` + +:::tip NOTE +After changing the config files you need to restart `yarn dev` +::: + +After setting up the Magento access you just need to run the Order2Magento worker which works on Redis based queue to process all the orders made by users: + +``` +yarn o2m +``` + +The code of this script is [located here](https://github.com/DivanteLtd/vue-storefront-api/blob/master/src/worker/order_to_magento2.js) -  so you can easily check how it’s working. + +## Synchronizing shopping carts + +By default shopping carts are not synchronized in the real time  -  just after the order is placed, Magento2 cart is created etc. + +This was limiting behavior because you need to keep the user cart most current all the time to get Magento2 shopping cart promotion rules into the action . + +We have option for that! If you have Magento2 API configured within the `vue-storefront-api` you just need to go to `vue-storefront/conf/local.json` and add + +```js +synchronize: true; +``` + +to `cart` section. Please check the [default config for reference](https://github.com/DivanteLtd/vue-storefront/blob/193cf44a6e936136fc19e22b45fe8dbc4b33f844/config/default.json#L8). diff --git a/docs/guide/installation/production-setup.md b/docs/guide/installation/production-setup.md new file mode 100644 index 0000000000..ba14eec3d6 --- /dev/null +++ b/docs/guide/installation/production-setup.md @@ -0,0 +1,422 @@ +# Production setup + +If you like to start developing sites using Vue Storefront, probably you need to start with the [Installation guide](linux-mac.md). For the development purposes you'll probably be using `yarn install` / `npm run installer` sequence which will setup Vue Storefront locally using the automated installer and prepared Docker images for having Elastic Search and Redis support. + +Development mode means you're using node.js based server as HTTP service and running the app on the `3000` TCP port. As it's great for local testing it's **not recommended** to use installer and direct user access to node.js in production configurations. + +## Production setup - bare VPS + +To run Vue Storefront in the production mode without Docker/Kubernetes you'll need the Virtual Private Server with `root` access (for the setup purposes). We assume that you're using `Debian GNU Linux` in the following steps. + +Assumptions for the rest of this tutorial: + +- You're having root access to Debian Linux machine; +- We'll be using the default local ports `3000` for [`vue-storefront`](https://github.com/DivanteLtd/vue-storefront) and `8080` for [`vue-storefront-api`](https://github.com/DivanteLtd/vue-storefront-api); the ports **should not be exposed** as they will be hidden behind **nginx proxy**; +- We're using **prod.vuestorefront.io** as a domain name - please replace it with your host URL address; +- We assume that you have SSL certificate for **prod.vuestorefront.io** (or your domain of course). SSL encryption is required for PWA + service workers; + +General Solution Architecture: +_USER -> nginx proxy -> vue-storefront / vue-storefront-api_ + +We'll be hiding the `vue-storefront` and `vue-storefront-api` services behind nginx proxy. You can use nginx for caching proxy, but in our case it will be just forwarding the requests without cache (as VS is pretty fast and caching is not required). The key features we're using are: SSL encryption, gzip-encoding, url routing (to merge `vue-storefront` and `vue-storefront-api` services under one domain). + +### Prerequisites + +Vue Storefront requires **Elastic Search** and the **Redis server** installed. By default, in the development mode, both dependencies are provided with the `docker-compose.yml` Docker images. However, for the production purposes we recommend to install the servers natively. + +For the purposes of this tutorial we will use default packages distributed along with the Debian operating systems, without any security hardening, config hardening operations. + +**Please make sure** that your security/devops team have taken a look at the configs you're using and do harden the server configuration before launching your app publicly! + +First, let's create the user (as root user): + +```bash +mkdir /home/www +useradd -m -d /home/www/vuestorefront vuestorefront +``` + +Then install the Elasticsearch and Redis (as root user): + +```bash +apt-get update +apt-get install curl +apt-get install git + +curl -sL https://deb.nodesource.com/setup_8.x | bash - +apt-get install -y nodejs +npm install -g yarn + +apt-get install redis-server + +apt-get install openjdk-8-jre +curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.9.deb +dpkg -i elasticsearch-5.6.9.deb +/etc/init.d/elasticsearch start + +apt-get install imagemagick +apt-get install nginx +``` + +### Nginx + +We decided to use **nginx** as a HTTP proxy - exposed in front of the users, handling the network traffic and dealing with the `vue-storefront` and the `vue-storefront-api` apps as a backend. + +This is a general rule of setting up a production node.js app which gives you a lot of flexibility regarding the SSL, gzip compression, URL routing and other techniques to be configured without additional hassle. You can use any other proxy server for this purpose - such as Varnish or Apache2 + mod_proxy. + +Some additional materials: + +- [How to setup production node.js app in the Digital Ocean environment (Ubuntu 16)](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-16-04) +- [How to setup nginx reverse proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) + +#### Nginx configuration + +[Here is the complete `/etc/nginx/sites-enabled/prod.vuestorefront.io` file](https://github.com/DivanteLtd/vue-storefront/tree/develop/doc/production-setup/etc/nginx/sites-enabled). + +Create nginx config file from the template (please run as a root user): + +```bash +curl https://raw.githubusercontent.com/DivanteLtd/vue-storefront/develop/doc/production-setup/etc/nginx/sites-enabled/prod.vuestorefront.io > /etc/nginx/sites-available/prod.vuestorefront.io +ln -s /etc/nginx/sites-available/prod.vuestorefront.io /etc/nginx/sites-enabled/prod.vuestorefront.io +``` + +**Install the SSL certificate** + +```bash +mkdir /etc/nginx/ssl +nano /etc/nginx/ssl/prod.vuestorefront.io.chained.crt +nano /etc/nginx/ssl/prod.vuestorefront.io.key +nano /etc/nginx/ssl/dhparam.pem +``` + +Now you can run the nginx: + +```bash +/etc/init.d/nginx restart +``` + +Please find the full comments on the following sections of the file below: + +```js +server { + listen 80; + server_name prod.vuestorefront.io; + return 301 https://prod.vuestorefront.io$request_uri; +} +``` + +This section runs the standard http://prod.vuestorefront.io and creates a wildcard redirect from http://prod.vuestorefront.io/* -> https://prod.vuestorefront.io/. SSL secured connection is a must for run PWA and use service-workers. + +```js +server { + listen 443 ssl; + server_name prod.vuestorefront.io http2; + + ssl on; +``` + +We're using `http2` but it's not required. This section is for setting up the SSL secured virtual host of Vue Storefront frontend. + +``` +ssl_certificate /etc/nginx/ssl/prod.vuestorefront.io.chained.crt; +ssl_certificate_key /etc/nginx/ssl/prod.vuestorefront.io.key; +``` + +We assume that the certificate related files are stored in the `/etc/nginx/ssl/`. Please point it to your certificate files. + +``` +ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; +ssl_prefer_server_ciphers on; +ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA; +ssl_ecdh_curve secp384r1; +ssl_session_timeout 10m; +ssl_session_cache shared:SSL:10m; +ssl_session_tickets off; +ssl_stapling on; +ssl_stapling_verify on; +resolver 8.8.8.8 8.8.4.4 valid=300s; +resolver_timeout 5s; + +ssl_dhparam /etc/nginx/ssl/dhparam.pem; + +add_header Strict-Transport-Security "max-age=31536000" always; +add_header X-Frame-Options DENY; +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; +add_header X-Robots-Tag none; +``` + +Here we go with the SSL settings - based on our best experiences from the past. Please read details in the [nginx documentation](http://nginx.org/en/docs/http/configuring_https_servers.html) if you like ;) + +``` +gzip on; +gzip_proxied any; +gzip_types + text/css + text/javascript + text/xml + application/javascript + application/json + text/json + text/html; +} +``` + +Vue Storefront SSR responses contain the full markup + JSON objects included for speed-up the first page view. Unfortunately - among with significant JS bundle sizes - it can generate a significant network load. We're optimizing it with using gzip compression server side. + +``` +location / { + proxy_pass http://localhost:3000/; +} +``` + +We're using [`proxy_pass`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) from the `ngx_http_proxy_module` to pull the content from the Vue Storefront nodejs server. Site will be available under https://prod.vuestorefront.io/ + +``` +location /assets/ { + proxy_pass http://localhost:3000/assets/; +} +``` + +The same module is used for providing user with the static assets. Assets will be available under: https://prod.vuestorefront.io/assets + +``` +location /api/ { + proxy_pass http://localhost:8080/api/; +} +``` + +The next proxy section is used for serving the API. It's a proxy to [`vue-storefront-api`](https://github.com/DivanteLtd/vue-storefront-api) app running on `8080` port (default config). API will be available under: https://prod.vuestorefront.io/api + +``` +location /img/ { + proxy_pass http://localhost:8080/img/; +} +``` + +The last proxy is used for serving product images. It's a proxy to [`vue-storefront-api`](https://github.com/DivanteLtd/vue-storefront-api) app running on `8080` port (default config). Images will be available under: https://prod.vuestorefront.io/img + +#### Apache2 configuration + +In case you are already using the apache2 web-server in your environment as well and can't (or don't want) to use nginx, you can also set up apache2 as an reverse proxy instead of nginx. This is done by adding this block to your apache2 virtual host. + +``` +ProxyRequests off + +ProxyPass /api/ http://localhost:8080/api/ +ProxyPassReverse /api http://localhost:8080/api/ + +ProxyPass /img/ http://localhost:8080/img/ +ProxyPassReverse /img http://localhost:8080/img/ + +ProxyPass /assets/ http://localhost:3000/assets/ +ProxyPassReverse /assets http://localhost:3000/assets/ + +ProxyPass / http://localhost:3000/ +ProxyPassReverse / http://localhost:3000/ +``` + +You also need to enable [mod_proxy](https://httpd.apache.org/docs/current/mod/mod_proxy.html) for this. + +### Vue Storefront and Vue Storefront API + +After you have the nginx set up, you should get a `502 error` when accessing the https://prod.vuestorefront.io. This is totally fine! We've just missed the most important step which is running backend services that will power up our installation. Now nginx is trying to connect to `localhost:3000` for `vue-storefront` and `localhost:8080` for `vue-storefront-api` without any success. + +We create a Linux user called `vuestorefront` and go to `/home/www/vuestorefront` which is our home directory. + +You need to clone the `vue-storefront` and the `vue-storefront-api` repos accordingly with the following commands: + +```bash +su vuestorefront +cd /home/www/vuestorefront +git clone https://github.com/DivanteLtd/vue-storefront.git +git clone https://github.com/DivanteLtd/vue-storefront-api.git +``` + +Then you will need to install the required node packages: + +```bash +cd /home/www/vuestorefront/vue-storefront-api +yarn install +``` + +... and ... + +```bash +cd /home/www/vuestorefront/vue-storefront +yarn install +``` + +It may take a few minutes. Once the modules are installed we can set configuration files for both services. + +#### Vue Storefront configuration + +The full configuration files are available here to download: [vue-storefront](https://github.com/DivanteLtd/vue-storefront/tree/develop/doc/production-setup/vue-storefront/config) and [vue-storefront-api](https://github.com/DivanteLtd/vue-storefront/tree/develop/doc/production-setup/vue-storefront-api/config). + +Please create the `vue-storefront-api/config/local.json` and `vue-storefront/config/local.json` files accordingly. + +```bash +curl https://raw.githubusercontent.com/DivanteLtd/vue-storefront/develop/doc/production-setup/vue-storefront-api/config/local.json > /home/www/vuestorefront/vue-storefront-api/config/local.json +``` + +... and ... + +```bash +curl https://raw.githubusercontent.com/DivanteLtd/vue-storefront/develop/doc/production-setup/vue-storefront/config/local.json > /home/www/vuestorefront/vue-storefront/config/local.json +``` + +Please find the key sections of the `vue-storefront/config/local.json` file described in below: + +```json +"elasticsearch": { + "httpAuth": "", + "host": "https://prod.vuestorefront.io/api/catalog", + "index": "vue_storefront_catalog" +}, +"storeViews": { + "mapStoreUrlsFor": [ + "de", + "it" + ], + "multistore": true, + "de": { + "disabled": false, + "elasticsearch": { + "httpAuth": "", + "host": "https://prod.vuestorefront.io/api/catalog", + "index": "vue_storefront_catalog_de" + } + }, + "it": { + "disabled": false, + "elasticsearch": { + "httpAuth": "", + "host": "https://prod.vuestorefront.io/api/catalog", + "index": "vue_storefront_catalog_it" + } + } +}, +``` + +We're setting up the product's endpoint to https://prod.vuestorefront.io/api/catalog (please use your domain accordingly of course). As you may notice, the `/api` url is proxied by the nginx to `localhost:8080` - our `vue-storefront-api` instance. + +```json +"cart": { + "synchronize": true, + "synchronize_totals": true, + "create_endpoint": "https://prod.vuestorefront.io/api/cart/create?token={{token}}", + "updateitem_endpoint": "https://prod.vuestorefront.io/api/cart/update?token={{token}}&cartId={{cartId}}", + "deleteitem_endpoint": "https://prod.vuestorefront.io/api/cart/delete?token={{token}}&cartId={{cartId}}", + "pull_endpoint": "https://prod.vuestorefront.io/api/cart/pull?token={{token}}&cartId={{cartId}}", + "totals_endpoint": "https://prod.vuestorefront.io/api/cart/totals?token={{token}}&cartId={{cartId}}", + "paymentmethods_endpoint": "https://prod.vuestorefront.io/api/cart/payment-methods?token={{token}}&cartId={{cartId}}", + "shippingmethods_endpoint": "https://prod.vuestorefront.io/api/cart/shipping-methods?token={{token}}&cartId={{cartId}}", + "shippinginfo_endpoint": "https://prod.vuestorefront.io/api/cart/shipping-information?token={{token}}&cartId={{cartId}}", + "collecttotals_endpoint": "https://prod.vuestorefront.io/api/cart/collect-totals?token={{token}}&cartId={{cartId}}", + "deletecoupon_endpoint": "https://prod.vuestorefront.io/api/cart/delete-coupon?token={{token}}&cartId={{cartId}}", + "applycoupon_endpoint": "https://prod.vuestorefront.io/api/cart/apply-coupon?token={{token}}&cartId={{cartId}}&coupon={{coupon}}" + }, +``` + +There are 27 more instances of `prod.vuestorefront.io` to be replaced with your production URL address in this file - please just do so :) + +#### Vue Storefront API configuration + +The [provided vue-storefront-api configuration](https://github.com/DivanteLtd/vue-storefront/tree/develop/doc/production-setup/vue-storefront-api/config) requires almost no changes. + +The only lines you need to alter are: + +```json +"imageable": { + "namespace": "", + "maxListeners": 512, + "imageSizeLimit": 1024, + "timeouts": { + "convert": 5000, + "identify": 100, + "download": 1000 + }, + "whitelist": { + "allowedHosts": [ + ".*divante.pl", + ".*vuestorefront.io" + ], + "trustedHosts": [ + ".*divante.pl", + ".*vuestorefront.io" + ] + }, + "keepDownloads": true, + "maxDownloadCacheSize": 1000, + "tmpPathRoot": "/tmp" +}, +"elasticsearch": { + "host": "localhost", + "port": "9200", + "indices": [ + "vue_storefront_catalog", + "vue_storefront_catalog_it", + "vue_storefront_catalog_de" + ] +} +``` + +You should put here the `allowedHosts` and `trustedHosts` for the Imageable - to download the product images. The domain name points to the **Magento2** instance where images are sourced. In this example Magento2 is running under **http://demo-magento2.vuestorefront.io**. + +#### Build VS + +Before we can run Vue Storefront and Vue Storefront API we should build it in the production mode. To do so please just execute the following commands: + +```bash +cd /home/www/vuestorefront/vue-storefront/ +yarn build +``` + +```bash +cd /home/www/vuestorefront/vue-storefront-api/ +yarn build +``` + +#### Data import + +Vue Storefront needs to have some data in the ElasticSearch to properly display products and categories. Of course you can install [mage2vuestorefront](https://github.com/DivanteLtd/mage2vuestorefront) and configure the data pump to synchronize and update the ElasticSearch index whenever data is being changed in Magento. For purposes of this tutorial we'll just restore the data from the JSON file. + +You can easily dump your current VS index using the following command (your local installation): + +```bash +cd vue-storefront-api +rm var/catalog.json +npm run dump +``` + +Now in the `var/catalog.json` you have your current database dump. Please transfer this file to the server for example using the following ssh command: + +```bash +ssh vuestorefront@prod.vuestorefront.io rm ~/vue-storefront-api/var/catalog.json +scp vue-storefront-api/var/catalog.json vuestorefront@prod.vuestorefront.io:~/vue-storefront-api/var/catalog.json +``` + +Then, after logging in to your `prod.vuestorefront.io` server as a `vuestorefront` you can run the following command to import the data: + +```bash +cd vue-storefront-api +npm run db new +npm run restore2main +npm run db rebuild +``` + +#### Running the Vue Storefront and Vue Storefront API + +After everything set, you can just start the `vue-storefront` and `vue-storefront-api`: + +```bash +cd vue-storefront-api +yarn start +cd vue-storefront +yarn start +``` + +Both applications use [`PM2` process manager](https://pm2.io/runtime) in the production mode (`start` commands) to manage and respawn the nodejs processes when needed. + +## Production setup - using Docker / Kubernetes + +To be prepared. diff --git a/docs/guide/installation/windows.md b/docs/guide/installation/windows.md new file mode 100644 index 0000000000..10785d541a --- /dev/null +++ b/docs/guide/installation/windows.md @@ -0,0 +1,107 @@ +# Installing on Windows + +Vue Storefront is based on open source technologies which SHOULD (in theory ;)) work perfectly well on most of the leading operating systems. However, we're developing the project using MacOS and Linux machines. + +## Requirements + +1. Please download [Docker for Windows](https://store.docker.com/editions/community/docker-ce-desktop-windows) and install it on your machine. [More Information](https://blog.jayway.com/2017/04/19/running-docker-on-bash-on-windows/) +2. Install [LTS version of Node.js for Windows](https://nodejs.org/en/download/) +3. Instal [Yarn](https://yarnpkg.com/en/docs/install) +4. You can use any editor for development BUT we're using [Visual Studio Code](https://code.visualstudio.com/) which is cool, free and very JS friendly! +5. You can [download Github Desktop](https://desktop.github.com/) to get access not only for fancy UI but for git toolset itself. + +## Installation of vue-storefront-api + +1. Open your cmdline of choice with [Git](https://git-scm.com/download/win) access or use Github desktop +2. Clone the [vue-storefront-api](https://github.com/DivanteLtd/vue-storefront-api) project: + +```bash +git clone https://github.com/DivanteLtd/vue-storefront-api.git vue-storefront-api +``` + +3. Go to `vue-storefront-api` in dir: + +```bash +cd vue-storefront-api +``` + +4. Install dependencies: + +```bash +yarn install +``` + +5. Run Docker containers required by `vue-storefront-api`: + +```bash +docker-compose up +``` + +This step can take some minutes. + +6. Restore products database and run latest migrations + +```bash +yarn restore +yarn migrate +``` + +7. Copy `config/default.json` to `config/local.json` +8. Run API: + +```bash +yarn dev +``` + +## Installation of vue-storefront + +1. Open your cmdline of choice with [Git](https://git-scm.com/download/win) access or use Github desktop +2. Clone the [vue-storefront](https://github.com/DivanteLtd/vue-storefront) project: + +```bash +git clone https://github.com/DivanteLtd/vue-storefront.git vue-storefront +``` + +3. Go to `vue-storefront` directory: + +``` +cd vue-storefront +``` + +4. Install dependencies: + +```bash +yarn install +``` + +5. Copy `config/default.json` to `config/local.json` +6. Images: because `vue-storefront-api` uses `imagemagick` and some nodejs cmdline bindings it can be difficult to run the image proxy on localhost/windows machine. Please point out the `vue-storefront` to image proxy provided by changing `config/local.json` `images.baseUrl`: + +```js +export default { + elasticsearch: { + httpAuth: '', + host: 'localhost:8080/api/catalog', + index: 'vue_storefront_catalog', + }, + // we have vue-storefront-api (https://github.com/DivanteLtd/vue-storefront-api) endpoints below: + orders: { + endpoint: 'localhost:8080/api/order/create', + }, + images: { + baseUrl: 'https://demo.vuestorefront.io/img/', + }, +}; +``` + +:::tip NOTE +We're using powerful node.js library for config files, check the docs to learn more on it: [https://github.com/lorenwest/node-config](https://github.com/lorenwest/node-config) +::: + +6. Run Vue Storefront Server: + +```bash +yarn dev +``` + +Now you should have Vue Storefront running on `localhost:3000`. diff --git a/docs/guide/integrations/magento.md b/docs/guide/integrations/magento.md new file mode 100644 index 0000000000..778388870b --- /dev/null +++ b/docs/guide/integrations/magento.md @@ -0,0 +1,3 @@ +# Magento + +_Work in progress_ diff --git a/docs/guide/integrations/multistore.md b/docs/guide/integrations/multistore.md new file mode 100644 index 0000000000..c0d95dcafe --- /dev/null +++ b/docs/guide/integrations/multistore.md @@ -0,0 +1,3 @@ +# Multistore Magento2 support + +_Work in progress_ diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000000..2108ca8858 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,9 @@ +{ + "scripts": { + "docs:dev": "vuepress dev", + "docs:build": "vuepress build" + }, + "dependencies": { + "vuepress": "^0.14.2" + } +} diff --git a/package.json b/package.json index 90320011ca..033413865a 100755 --- a/package.json +++ b/package.json @@ -171,6 +171,7 @@ "core/i18n", "core/store", "src/extensions/*", - "src/themes/*" + "src/themes/*", + "docs" ] }