# Nivesh Saharan (nive.sh) — full index > Senior full-stack engineer and three-time founder based in Gurugram, India. I build Shopify apps and storefronts, custom web platforms, mobile apps and EVM blockchain products for brands and product teams worldwide. Nivesh Saharan is a full-stack engineer and three-time founder based in Gurugram, India (IST, UTC+5:30), writing production code since 2012. He co-founded Yopify (2014–2017), Centire Inc. (2014–2020) and Sellify Apps (2017–2020), shipped 9 public Shopify apps, and runs 2 live products: Payback (iOS and Android, free on the web as OweJar at https://owejar.com) and Hoursmith (https://hoursmith.app), flat-fee time tracking, tasks and invoicing for freelancers and agencies. Since 2020 he works independently with brands and product teams worldwide, with client partnerships running since 2017. Key facts: - Services: Custom Web and Mobile Engineering; Shopify Engineering and Customization; EVM Blockchain Product Development - Core stack: PHP/Laravel, JavaScript/TypeScript, React, Next.js, Vue.js, Node.js, Shopify (Liquid, Admin API, Functions, Scripts), MySQL, NGINX, AWS, DigitalOcean, Solidity/EVM, iOS & Android - Contact: hey@nive.sh · Book a call: https://tidycal.com/nivesh/30 - Full index with article bodies: https://nive.sh/llms-full.txt ## Services - [Custom Web and Mobile Engineering](https://nive.sh/services/custom-web-mobile-engineering): Production-grade web platforms and mobile experiences built with clear architecture, measurable performance, and maintainable code. - [Shopify Engineering and Customization](https://nive.sh/services/shopify-engineering-and-customization): End-to-end Shopify engineering to improve conversion, unlock custom workflows, and keep releases stable during growth and campaign cycles. - [EVM Blockchain Product Development](https://nive.sh/services/evm-blockchain-product-development): Design and build secure EVM smart-contract-based products with practical UX and maintainable full-stack systems. ## Clients - Fabric Wholesale Direct (Since Jan 2017, 9 yrs): Shopify theme development, store customization, discount app/function workflows, ShipStation integrations, and shipping automation tooling. - Truck Mount Forums (Since Jan 2018, 8 yrs): Shopify theme engineering, advanced discount app development, recurring sales setup support, and third-party integration work. - INNBeauty Project (Since Jan 2020, 6 yrs): Shopify Plus redesign, custom bundle and discount app development, ongoing sales engineering support, and day-to-day store enhancements. - By Simran (Since Jan 2024, 2.5 yrs): Shopify store engineering including a custom-built returns and warranty portal, internal workflow apps, and ongoing operational enhancements. - Confidential D2C Nutrition Brand (Since Jan 2023, 3 yrs): Storefront re-architecture and conversion optimization program. - Confidential Fintech Platform (Apr 2022 – Sep 2024, 2 yrs): Laravel platform modernization with payment workflow hardening. - Details: https://nive.sh/clients ## Case studies - [Shopify Growth Suite for High-Volume Merchants](https://nive.sh/case-studies/shopify-growth-suite): Built and iterated multiple Shopify conversion apps focused on upsell, social proof, and checkout experience improvements. - [Self-Serve Token Launch Platform on EVM Chains](https://nive.sh/case-studies/token-launch-platform): Created a product that allows users to launch verified ERC-20 tokens across major EVM chains without writing smart contract code. - [Enterprise Web Platform Modernization](https://nive.sh/case-studies/enterprise-web-platform-modernization): Modernized and extended custom client web applications with stronger performance, cleaner integration layers, and improved maintainability. ## Products - [Payback / OweJar](https://nive.sh/apps/payback): Track who owes whom. Split expenses. Settle up. Record money you gave, got and spent, split bills with friends and groups, follow repayments, and ask ChatGPT or Claude how things stand. On the web it is called OweJar, and every feature there is free. Platforms: iOS, Android, Web. Web: https://owejar.com App Store: https://apps.apple.com/app/id6761522271 Google Play: https://play.google.com/store/apps/details?id=app.ccc.payback - [Hoursmith](https://nive.sh/apps/hoursmith): Projects, tasks, time and invoices in one clean workflow. Lightweight task management, billable time tracking, expenses and one-off or recurring invoicing for freelancers and small agencies, with a flat workspace price instead of per-seat fees. Platforms: Web. Web: https://hoursmith.app ## Public Shopify apps (built 2014–2020 at Yopify and Sellify Apps) - ULTIMATE Cart Drawer: Slide-out cart drawer for faster checkout paths. (https://apps.shopify.com/ultimate-cart-drawer) - ULTIMATE Countdown Timer: Urgency timers for campaigns and launches. (https://apps.shopify.com/ultimate-countdown-timer) - ULTIMATE Currency Converter: Localized pricing for international shoppers. (https://apps.shopify.com/ultimate-currency-converter) - Surveyor: Customer surveys for merchants. (https://apps.shopify.com/surveyor) - ULTIMATE Post Purchase Upsell: Post-purchase offers that lift average order value. (https://apps.shopify.com/profit-panda) - ULTIMATE Announcement Bar: Storefront announcement bars and promotions. (https://apps.shopify.com/ultimate-announcement-bar-1) - Yo: Social proof notifications for storefronts. - Thank You Page Customizer: Customizable post-checkout thank-you pages. (https://apps.shopify.com/thank-you-page) - Sticky Buy Button: Always-visible add-to-cart on product pages. ## Articles - [Arrays and Tuples](https://nive.sh/articles/arrays-and-tuples): There are two primitive compound types in Rust: Arrays and Tuples. - [A Practical guide to use Arrays and Objects in JavaScript](https://nive.sh/articles/practical-guide-to-use-array-and-objects-in-javascript): JavaScript objects and arrays are fundamental data structures used to organize and store data. In this comprehensive guide, we will explore the concepts of objects and arrays, provide relatable examples for both technical and non-technical individuals, and delve into safe techniques for copying and modifying these data structures. By following the discussed techniques, you can ensure data integrity, avoid unintended side effects, and confidently work with JavaScript data. - [Hello, Rust!](https://nive.sh/articles/hello-rust): Welcome to Rust for JavaScript Developers! It's fantastic to have you here. Let's dive right in. - [Scalars](https://nive.sh/articles/scalars): Rust is a statically typed programming language. This means that all values must have a known type at compile time. So how did we get away without adding annotations in our Hello, Rust example? The Rust compiler is quite excellent at type inference and will often infer types for your values and only ask you to specify a type if it can't. - [Statements and Variables](https://nive.sh/articles/statements-and-variables): Code is typically composed of statements. Statements consist of one or more values and operators. Initialising a variable, setting it to the return value of a function call, even calling a macro (like the println macro we saw a while ago) are all examples of statements. - [Create your own token on Ethereum, Polygon or Binance Smart Chain in a minute](https://nive.sh/articles/create-your-own-erc20-token-on-ethereum-polygon-binance-in-a-minute): Creating your own token has never been this easy and you can now create your own token without any blockchain programming knowledge in just under a minute. - [Say hello to TypeScript](https://nive.sh/articles/say-hello-to-typescript): TypeScript is a superset of JavaScript that has optional typing and compiles to plain JavaScript. Technically its JavaScript with static typing, whenever you want to have it. - [[Shopify Script] 2 or more variants within the same product ID get 10% off](https://nive.sh/articles/2-or-more-variants-within-the-same-product-get-10-percent-off): In this article, we are going to create a Shopify Script that gives 10% discount on the line items having at least 2 quantities of same product. - [Powerful ways to Supercharge your NGINX server and improve its performance](https://nive.sh/articles/powerful-ways-to-supercharge-your-nginx-server-and-improve-its-performance): You don’t need to be a DevOps expert to make the optimizations explained in this post. Anyone who is new to web applications and is using NGINX can use these steps. All you have to do is edit your NGINX config file. - [Different types of Shopify apps](https://nive.sh/articles/types-of-shopify-apps): In this lesson, we will learn about four types (Public, private, custom and draft apps) of Shopify apps and different characteristics for each type of app. - [Laravel/Php - How to serve gzipped content from S3](https://nive.sh/articles/how-to-serve-gzipped-content-from-s3-in-laravel-php): Until last month, our apps were serving JavaScript files from s3 without any compression and one of our customer asked us if we can enable gzip compression on the assets being served. - [A Few Quick Terminal Tips](https://nive.sh/articles/few-quick-terminal-tips): Few tips for fast & productive work on a terminal... - [A Practical guide to use LocalStorage and SessionStorage](https://nive.sh/articles/practical-guide-to-use-localstorage-and-sessionstorage): SessionStorage and LocalStorage are a simple key/value pair storage and only the string type of data can be stored. SessionStorage and LocalStorage both has same API. Both storage objects provide same methods and properties. - [A Practical guide to use Fetch API](https://nive.sh/articles/practical-guide-to-use-fetch-api): Fetch is a promise based Javascript API for making asynchronous HTTP requests. It is a clean, simple, powerful and a flexible API to get/send data from/to a server. - [A better approach to keep Laravel .env files for multiple environments](https://nive.sh/articles/better-approach-to-keep-env-files-for-multiple-environments): Laravel comes with a .env file by default and it is called .env.example and we create a copy of .env.example file as .env... - [My Nginx configurations for Virtual Host, SSL etc.](https://nive.sh/articles/my-nginx-configurations-for-virtual-host-ssl-etc): Here are my configurations I use for my Laravel apps. Hope someone find these useful. ## About & contact - [About](https://nive.sh/about): experience timeline, toolbox and principles - [Contact](https://nive.sh/contact): book a call or send a project brief - LinkedIn: https://www.linkedin.com/in/niveshsaharan - GitHub: https://github.com/niveshsaharan - RSS: https://nive.sh/rss.xml --- ## Experience - Independent — Full-stack engineering partner (Oct 2020 – present, Gurugram, India · remote worldwide): Senior execution layer for Shopify brands, founders and product teams: storefronts, custom apps, integrations, mobile apps and EVM products. - Long-term Shopify partnerships with Fabric Wholesale Direct, Truck Mount Forums, INNBeauty Project and By Simran. - Shipped Payback to the App Store and Google Play, with OweJar as its free web version, and launched Hoursmith, flat-fee time tracking and invoicing for freelancers and agencies. - Built Bake My Token, a self-serve ERC-20 token launch platform for EVM chains. - Sellify Apps — Co-Founder (Oct 2017 – Sep 2020): Helped merchants grow their Shopify stores and built public and private Shopify apps. - Built the ULTIMATE app suite: cart drawer, countdown timer, currency converter, post-purchase upsell and announcement bar. - Shipped conversion apps across upsell, social proof and post-purchase use cases for high-volume merchants. - Centire Inc. — Co-Founder (Aug 2014 – Sep 2020, Gurugram, India): Designed and developed clean, modern websites and web applications with rich user experiences, specializing in the Laravel ecosystem. - Full-stack delivery across front-end and back-end for client web platforms. - Led enterprise web platform modernization with cleaner integration layers and predictable deployments. - Yopify — Co-Founder (Mar 2014 – Sep 2017): Built public Shopify apps for merchants on the Shopify App Store. - First public Shopify apps, including storefront tools used by merchants worldwide. - Cogniter Technologies — Web Developer (Feb 2014 – Apr 2014): Web development across client delivery projects. - NetSet Software Solutions — Web Developer (Aug 2012 – Feb 2014, Chandigarh, India): Started out building PHP and JavaScript web applications for agency clients. - Education: Kurukshetra University, Bachelor of Technology (B.Tech), Information Technology ## Toolbox - Languages: PHP, JavaScript, TypeScript, Ruby (Shopify Scripts), Solidity, Rust (writing about it) - Frameworks & UI: Laravel, React, Next.js, Vue.js, Node.js, Tailwind CSS - Commerce: Shopify themes (Liquid · OS 2.0), Shopify apps & extensions, Admin API & webhooks, Functions, Scripts & discounts, Checkout & post-purchase, ShipStation & fulfillment - Mobile: iOS, Android, App Store & Play releases, Local-first data & encrypted backups - Infrastructure: AWS, DigitalOcean, NGINX, MySQL, Git, CI, QA & staging-first releases - Web3: Ethereum, Polygon, BNB Chain, ERC-20 & smart contracts, Wallet integrations ## Numbers - 14+ years writing production code (since 2012) - 3 companies co-founded - 9 public Shopify apps shipped - 2 live products (1 on iOS and Android, 1 web-only) - Longest client partnership: 9 years and ongoing - 16 articles published ## Services in detail ### Custom Web and Mobile Engineering URL: https://nive.sh/services/custom-web-mobile-engineering Audience: Founders and product teams shipping greenfield or legacy modernization projects. Summary: Production-grade web platforms and mobile experiences built with clear architecture, measurable performance, and maintainable code. Deliverables: - Product architecture and technical roadmap - Frontend and backend implementation - API integrations, observability, and deployment automation - Performance and accessibility optimization Process: 1. Discovery and requirements audit 2. Technical specification with milestones 3. Iterative implementation with weekly demos 4. Hardening, QA, and launch support FAQ: - Q: Can you join an existing codebase? A: Yes. Most engagements begin with a code and infra audit, then a clear stabilization plan. - Q: Do you support both Android and iOS? A: Yes. I build and ship cross-platform mobile solutions with production release workflows. ### Shopify Engineering and Customization URL: https://nive.sh/services/shopify-engineering-and-customization Audience: D2C brands, Shopify Plus teams, and agencies that need senior execution across storefront, apps, checkout logic, and operations. Summary: End-to-end Shopify engineering to improve conversion, unlock custom workflows, and keep releases stable during growth and campaign cycles. Intro: I help merchants ship Shopify work that directly affects revenue and operations: faster storefronts, smarter conversion logic, stable app integrations, and internal tooling that saves team time. Engagements are implementation-first, not strategy-only. Deliverables: - Theme architecture, UX refinements, and storefront performance optimization - Custom Shopify apps, app extensions, and merchant tooling - Checkout, cart, bundles, and discount/Function workflow engineering - Integrations and automation for shipping, fulfillment, and post-purchase operations - Release stabilization, QA workflows, and ongoing growth-focused support Process: 1. Revenue-path audit across homepage, PDP, cart, checkout, and post-purchase workflows 2. Prioritized implementation plan with clear business impact, dependencies, and rollout sequencing 3. Execution in staging-first cycles with QA across devices, buyer journeys, and edge-case order paths 4. Launch hardening with analytics checks, iteration backlog, and optional ongoing support Credibility: - Co-founded Sellify Apps and Yopify, where I built and shipped Shopify apps used for upsell, social proof, and post-purchase conversion workflows. - Long-term Shopify delivery partner for Fabric Wholesale Direct (since 2017), including theme engineering, discount logic, shipping automation, and operational tooling. - Delivered Shopify Plus redesign and custom bundle/discount workflows for INNBeauty Project, with recurring sales-engineering support. - Built custom returns and warranty workflows plus internal tooling for By Simran, improving post-purchase operations. - Supported recurring campaign launches, maintenance, and stabilization for stores that cannot afford checkout or release instability. #### Storefront and Theme Engineering Production-ready Shopify theme work that keeps merchandising flexible while improving speed, UX clarity, and release safety. Capabilities: - Theme architecture cleanup for long-term maintainability (OS 2.0 sections, reusable components, cleaner templates) - PDP/collection/cart UX refinements focused on reducing buyer friction - Mobile-first optimization and performance hardening across high-traffic templates - Theme updates and controlled rollout workflows for active campaign calendars Examples: - Led a full Shopify storefront redesign and theme upgrade for INNBeauty Project while supporting ongoing campaign execution. - Delivered long-term storefront customization and performance improvements for Fabric Wholesale Direct. - Handled ongoing theme upgrades and SEO/speed-focused refinements for TruckMount Forums. #### Conversion, AOV, and Merchandising Workflows Custom buyer-path logic for upsells, bundles, promotions, and offer orchestration that standard apps often cannot model correctly. Capabilities: - Upsell and cross-sell logic tied to product type, cart state, or campaign rules - Bundle and build-your-own-pack experiences with inventory-aware behavior - Offer sequencing for recurring sales events and seasonal promotions - Cart UX and messaging improvements for clearer value communication before checkout Examples: - Built multiple conversion-focused Shopify apps (upsell, social proof, and post-purchase flows) for Sellify Apps. - Implemented advanced build-your-own-bundle and discount workflows for INNBeauty Project. - Supported recurring sales setup and conversion operations for TruckMount Forums. #### Custom Shopify App Development and Extensions Build custom apps when off-the-shelf tools are limiting growth, operational control, or pricing logic requirements. Capabilities: - Custom app architecture for single-store and multi-merchant use cases - Embedded app UI flows and merchant-friendly settings/configuration experiences - Webhook-driven workflows, background jobs, and reliable data synchronization - Build-vs-buy evaluation when deciding between custom app work and third-party installs Examples: - Built and launched Shopify public apps while co-founding Yopify and Sellify Apps. - Delivered custom discount-focused Shopify apps for merchants with advanced rule requirements. - Created internal utility apps and operational tools for merchant teams with unique day-to-day workflows. #### Checkout, Discounts, and Function-Level Customization Engineer complex discounting and checkout behavior where revenue logic is too specific for prebuilt plugin settings. Capabilities: - Advanced discount logic based on product, quantity, customer segment, and cart composition - Bundle pricing rules, stack constraints, and campaign-specific conditions - Shopify Functions and discount workflow implementation for precise pricing behavior - Checkout-path reliability improvements and QA for high-volume campaign periods Examples: - Implemented discount app/function workflows across multiple long-term client stores. - Built advanced discount and bundle logic for Shopify Plus requirements at INNBeauty Project. - Supported checkout reliability improvements for a confidential D2C nutrition brand. #### Integrations, Shipping, and Operations Automation Connect Shopify with fulfillment and internal workflows so teams spend less time on manual operations and exception handling. Capabilities: - ShipStation and shipping workflow integrations with custom business rules - Automation for repetitive order, fulfillment, and support-side tasks - Operational dashboards and merchant-side tools for internal team productivity - Third-party integration support with guarded rollout and monitoring plans Examples: - Built ShipStation integrations and shipping-focused utility apps for Fabric Wholesale Direct. - Partnered on Shipping+, an automation product for carrier rate shopping and warehouse workflow efficiency. - Implemented third-party integration and workflow support for TruckMount Forums across recurring release cycles. #### Post-Purchase, Returns, and Customer Operations Improve post-purchase experiences with tailored workflows that reduce support load and increase customer confidence. Capabilities: - Returns and warranty portal implementation tailored to your policies and internal processes - Post-purchase experience enhancements tied to support and retention goals - Internal workflow apps for operations and customer service teams - Process design for handling edge cases and reducing manual interventions Examples: - Built a custom returns and warranty portal for By Simran. - Developed team-specific internal tooling for post-purchase operations. - Delivered ongoing operational enhancements across integrations, UX improvements, and conversion maintenance. #### Stabilization, Maintenance, and Growth Retainers Ongoing technical ownership for Shopify stores that need predictable shipping velocity without quality regressions. Capabilities: - Audit and cleanup of unstable theme/app setups - Release hardening for campaign-heavy stores with tight timelines - Continuous optimization backlog covering conversion, speed, and operational efficiency - Senior hands-on implementation instead of ticket-only advisory Examples: - Stabilized release cycles and improved checkout reliability for a confidential D2C engagement. - Provided recurring Shopify maintenance, campaign support, and integration work for TruckMount Forums. - Delivered long-term Shopify execution for Fabric Wholesale Direct with both storefront and operations impact. FAQ: - Q: Do you work with existing themes and apps? A: Yes. Most work is done on live stores with safe staging workflows and controlled rollouts. - Q: Can you help with app strategy? A: Yes. I help define build-vs-buy decisions, app architecture, and launch execution. - Q: Can you handle both quick wins and complex builds? A: Yes. I usually split work into two tracks: immediate conversion/operations wins and deeper structural work that reduces long-term technical drag. - Q: Do you work only on Shopify Plus? A: No. I work across standard Shopify and Shopify Plus stores. The implementation options differ, so I map solutions to your actual plan and constraints. - Q: Can you collaborate with our agency or in-house team? A: Yes. I often work as a senior execution layer alongside design, growth, or agency teams with clear ownership and delivery accountability. - Q: What if our current setup is messy? A: That is common. I start with a stability and risk audit, then create a phased plan to fix high-impact issues first before layering new features. - Q: Can you support ongoing releases after initial delivery? A: Yes. Many partnerships are structured as ongoing Shopify execution retainers for campaign support, optimization, and maintenance. ### EVM Blockchain Product Development URL: https://nive.sh/services/evm-blockchain-product-development Audience: Teams launching tokenized products, smart contracts, and web3 integrations. Summary: Design and build secure EVM smart-contract-based products with practical UX and maintainable full-stack systems. Deliverables: - Smart contract architecture and implementation - Web3 frontend and wallet integrations - Chain deployment and verification workflows - Monitoring and post-deploy support Process: 1. Use-case and risk review 2. Contract and app architecture definition 3. Development, testing, and staging deployment 4. Mainnet launch support and iteration FAQ: - Q: Which EVM chains do you support? A: Ethereum, Polygon, BNB Chain, and other EVM-compatible networks based on product needs. - Q: Can you also build the non-web3 backend? A: Yes. I handle full-stack delivery for dashboard, APIs, and integrations around contracts. ## Clients in detail ### Fabric Wholesale Direct Engagement: Since Jan 2017 (9 yrs, ongoing) Website: https://fabricwholesaledirect.com Project: https://shippingplus.co Scope: Shopify theme development, store customization, discount app/function workflows, ShipStation integrations, and shipping automation tooling. Outcomes: - Supported long-term Shopify delivery for Fabric Wholesale Direct with custom storefront and operational enhancements. - Built ShipStation integrations and shipping-focused utility apps, including a Chrome extension for rate shopping workflows. - Partnered on Shipping+, an automation product focused on carrier rate shopping and warehouse process efficiency. Services: Shopify Engineering and Customization, Custom Web and Mobile Engineering ### Truck Mount Forums Engagement: Since Jan 2018 (8 yrs, ongoing) Website: https://shop.truckmountforums.com/ Project: https://pro.truckmountforums.com/ Scope: Shopify theme engineering, advanced discount app development, recurring sales setup support, and third-party integration work. Outcomes: - Delivered ongoing Shopify maintenance and sales campaign setup across recurring release cycles. - Built a custom Shopify app for advanced discounting and integrated multiple external systems. - Supported theme upgrades, membership-program workflows, and continued SEO/speed performance improvements. Services: Shopify Engineering and Customization, Custom Web and Mobile Engineering ### INNBeauty Project Engagement: Since Jan 2020 (6 yrs, ongoing) Website: https://innbeautyproject.com/ Scope: Shopify Plus redesign, custom bundle and discount app development, ongoing sales engineering support, and day-to-day store enhancements. Outcomes: - Led a full website redesign and theme upgrade to modernize the storefront experience. - Built custom Shopify apps and extensions for advanced discounting and build-your-own-bundle workflows. - Supported conversion operations with recurring sales setup, email layout improvements, and performance optimization work. Services: Shopify Engineering and Customization, Custom Web and Mobile Engineering ### By Simran Engagement: Since Jan 2024 (2.5 yrs, ongoing) Website: https://bysimran.com/ Scope: Shopify store engineering including a custom-built returns and warranty portal, internal workflow apps, and ongoing operational enhancements. Outcomes: - Built a custom returns and warranty portal tailored to post-purchase support workflows. - Developed custom Shopify apps for internal requirements and team-specific operational tooling. - Delivered day-to-day storefront improvements across integrations, UX refinements, and conversion-focused maintenance. Services: Shopify Engineering and Customization, Custom Web and Mobile Engineering ### Confidential D2C Nutrition Brand (confidential) Engagement: Since Jan 2023 (3 yrs, ongoing) Scope: Storefront re-architecture and conversion optimization program. Outcomes: - Stabilized the release cycle during active campaign periods. - Improved checkout flow reliability and reduced buyer drop-off. Services: Shopify Engineering and Customization ### Confidential Fintech Platform (confidential) Engagement: Apr 2022 – Sep 2024 (2 yrs) Scope: Laravel platform modernization with payment workflow hardening. Outcomes: - Improved reliability of critical transaction and reconciliation paths. - Reduced regression risk with tighter architecture and release controls. Services: Custom Web and Mobile Engineering ## Case studies in detail ### Shopify Growth Suite for High-Volume Merchants URL: https://nive.sh/case-studies/shopify-growth-suite Client: Sellify Apps · Type: Shopify apps Challenge: Merchants needed conversion-focused features that could be installed quickly, configured easily, and scaled reliably during campaigns. Solution: Designed a modular app architecture, implemented merchant-friendly configuration flows, and shipped repeatable release and support workflows. Outcomes: - Delivered multiple production Shopify apps across upsell, social proof, and post-purchase use cases. - Reduced merchant setup friction with cleaner onboarding and configuration UX. - Established a maintainable architecture for faster feature rollout cycles. Stack: Shopify APIs, PHP, Laravel, JavaScript ### Self-Serve Token Launch Platform on EVM Chains URL: https://nive.sh/case-studies/token-launch-platform Client: Bake My Token · Type: Web3 product Challenge: Non-technical users needed a safe and simple way to launch token contracts while minimizing manual deployment complexity. Solution: Implemented guided workflows for token configuration, deployment handling, and verification support across Ethereum-compatible networks. Outcomes: - Enabled non-technical founders to launch token projects with a self-serve flow. - Unified multi-chain deployment paths under one product experience. - Created a reusable launch pipeline for future chain expansion. Stack: Solidity, EVM Chains, Web3 Integrations, Node.js ### Enterprise Web Platform Modernization URL: https://nive.sh/case-studies/enterprise-web-platform-modernization Client: Centire · Type: Platform modernization Challenge: Legacy web systems were slowing feature delivery and making cross-service integrations difficult to maintain. Solution: Led architecture cleanup, implemented integration pipelines, and delivered iterative upgrades while preserving business continuity. Outcomes: - Improved release confidence with a cleaner architecture and predictable deployment flow. - Reduced integration complexity between product and operational systems. - Enabled faster execution on client-requested enhancements. Stack: Laravel, JavaScript, MySQL, Cloud Infrastructure ## Products in detail ### Payback (OweJar on the web) URL: https://nive.sh/apps/payback Category: Dues & splits · Platforms: iOS, Android, Web · Status: Live on the App Store and Google Play · Free on the web as OweJar Tagline: Track who owes whom. Split expenses. Settle up. Summary: Record money you gave, got and spent, split bills with friends and groups, follow repayments, and ask ChatGPT or Claude how things stand. On the web it is called OweJar, and every feature there is free. Highlights: - I gave, I got and I spent entries, partial and full repayments, and one clear balance for every person. - Split expenses equally, by exact amounts or by percentage. Groups, guests and invite links are free for every account. - Bills, subscriptions and daily deliveries with due dates and reminders, plus recurring entries that repeat on their own. - Shareable statements as PDF, print or private link, and monthly insights by category and group. Currencies are never mixed. - Connect ChatGPT, Claude or any MCP assistant with permissions you choose. It never connects to your bank or moves money. Pricing: Free on the web for every account. OweJar Pro, bought in the phone app, adds multi-device sync. Privacy: Phone records live on your device first, with encrypted backups you control. Only you see your private book. Languages: Nine languages in the phone app; English and Hindi on the web. Web: https://owejar.com App Store: https://apps.apple.com/app/id6761522271 Google Play: https://play.google.com/store/apps/details?id=app.ccc.payback Help center: https://owejar.com/help Connect an AI assistant: https://owejar.com/help/connect-ai-assistant ### Hoursmith URL: https://nive.sh/apps/hoursmith Category: Time tracking & invoicing · Platforms: Web · Status: Live at hoursmith.app · Free for up to 3 members Tagline: Projects, tasks, time and invoices in one clean workflow. Summary: Lightweight task management, billable time tracking, expenses and one-off or recurring invoicing for freelancers and small agencies, with a flat workspace price instead of per-seat fees. Highlights: - Track time with a one-click timer, by hand, or from the Chrome extension. Every entry follows its project’s billing policy, so fixed-fee and internal work stays out of hourly invoices. - Draft invoices from un-invoiced hours, fixed-fee balances, expenses with receipts and custom lines. Recurring invoices can auto-send beneath a billing ceiling and never charge the customer automatically. - Clients pay through Stripe Connect straight into your own Stripe account. Hoursmith never holds or routes your funds, and invoices mark themselves paid. - Invoices go out from your own domain through SMTP, Amazon SES or Resend, with a shareable invoice page that shows when the client has viewed it. - Kanban boards and lists, client and project dashboards, saved views, role-based team permissions, a typed REST API and an MCP server for ChatGPT, Claude and other assistants. Pricing: Free for up to 3 members. Studio is a flat $5/month for up to 10 members; Agency is $9.99/month per 25-seat quantity. Annual billing saves 16%. Scope: A web application on purpose: no Gantt charts, dependencies, resource planning, CRM, accounting or native mobile apps. Imports: Paymo importer, CSV and Excel import, plus a REST API and MCP server for everything else. Web: https://hoursmith.app Features: https://hoursmith.app/features Pricing: https://hoursmith.app/pricing About: https://hoursmith.app/about ## Frequently asked questions - Q: What kind of work do you take on? A: Three tracks: Shopify engineering and customization (themes, custom apps, checkout and discount logic, integrations), custom web and mobile engineering (greenfield products and legacy modernization), and EVM blockchain product development (smart contracts plus the full-stack around them). - Q: Can you join an existing codebase or a messy Shopify setup? A: Yes. Most engagements begin with a code, theme and infrastructure audit, followed by a phased plan that fixes high-impact issues first before layering new features. - Q: Do you work only on Shopify Plus? A: No. I work across standard Shopify and Shopify Plus stores. The implementation options differ, so solutions are mapped to your actual plan and constraints. - Q: Can you collaborate with our agency or in-house team? A: Yes. I often work as a senior execution layer alongside design, growth or agency teams, with clear ownership and delivery accountability. - Q: Where are you based, and how do you work with teams abroad? A: I am based in Gurugram, India (IST, UTC+5:30) and work remotely with teams worldwide. Work runs in staging-first cycles with weekly demos, written specs and clear milestones, so time zones rarely get in the way. - Q: How do engagements usually start? A: With a short discovery call to align on outcomes, timeline and constraints. From there you get a technical specification with milestones, then iterative implementation with weekly demos through launch. - Q: Do you offer ongoing support after launch? A: Yes. Many partnerships continue as ongoing execution retainers for campaign support, optimization, maintenance and new features. --- ## Articles (full text) ### Arrays and Tuples - URL: https://nive.sh/articles/arrays-and-tuples - Published: Jun 27, 2023 - Reading time: 5 min read - Categories: JavaScript, Rust - Tags: rust, javascript - Series: Hello, Rust! > There are two primitive compound types in Rust: Arrays and Tuples. ## Introduction There are two primitive compound types in Rust: Arrays and Tuples ## Arrays You've probably heard of Arrays before. Arrays in Rust are similar and dissimilar to Arrays in JavaScript in different ways. Let's talk about the similarities first. ```rust let spidermen = ["Tobey Maguire", "Andrew Garfield", "Tom Holland"]; ``` The statement above is both valid JavaScript and Rust. Like JavaScript, you can access the elements on the array ```spidermen``` by using zero based indices, for example Andrew Garfield is ```spidermen[1]```. This is pretty much where the similarities end. In Rust, all elements in an Array must be of the same type. The above example works because all the elements in ```spidermen``` are String slices (more on these soon) but if you tried to create: ```rust let spidermen = ["Tobey Maguire", "Andrew Garfield", "Tom Holland", 4]; ``` It would fail with: ```bash error[E0308]: mismatched types --> hello-rust.rs:2:73 | 2 | let spidermen = ["Tobey Maguire", "Andrew Garfield", "Tom Holland", 4]; | ^ expected `&str`, found integer error: aborting due to previous error ``` Arrays in Rust also have a strictly defined length and since there is no ```undefined``` or ```null``` in Rust, arrays cannot be sparse. This means that you can't push another element to the above array when they inevitably cast a new Spider-Man in a few years. To have a list of items that can grow or shrink in size, you need a ```Vec```! We'll learn about these later. Given these limitations, Arrays in Rust are useful for lists with known sizes and elements of an homogenous type, like a list of top three scores at your local bowling alley. ```rust let top_scores: [u32; 3] = [292, 170, 140]; ``` Notice the semicolon separator in the type annotation: ```u32``` is the type of each element of which there are ```3```. You can even initialise an Array with a length and a default value for each element but as we've learnt previously, it needs to be mutable (declared with ```mut```) if you want to reassign values! ```rust let mut top_scores = [0; 3]; top_scores[0] = 292; top_scores[1] = 170; top_scores[2] = 140; ``` In the above example, ```0``` is the default value of each element and there are ```3``` of them. Unlike JavaScript, the length of an Array in Rust is not a property but a method on the Array called ```len```. ```rust println!("{}", top_scores.len()); ``` Finally, let's try to print the entire Array with ```println!```. ```rust println!("{}", top_scores); ``` This will throw an error during compilation that is along the lines of: ```bash error[E0277]: `[{integer}; 3]` doesn't implement `std::fmt::Display` --> hello-rust.rs:6:20 | 6 | println!("{}", top_scores); | ^^^^^^^^^^ `[{integer}; 3]` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `[{integer}; 3]` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error ``` We'll get into what this means in detail when we dive deep into Traits but for now, you can print the array as follows ```rust println!("{:?}", top_scores); ``` The ```:?``` makes ```println!``` use the Debug "trait" instead of the default ```Display``` and lets you quickly print out values as you learn. ## Tuples Tuples are the other primitive compound type in Rust. JavaScript doesn't have Tuples so this may seem a little foreign but you'll appreciate these. Tuples are simply put a collection of multiple values of various types but with a fixed length again! For example, here is a mutable Tuple of product name, cost and availability: ```rust let mut product = ("iPhone 12 Pro Max", 1099, true); ``` We can set the tuple to: ```rust product = ("PS5", 499, false); ``` But not to: ```rust product = ("PS5", 499.99, false); ``` Because product was initialised as a ```(&str, i32, bool)``` tuple and we tried to set the middle value to a floating point value. Tuples can have multiple types in them but the type of a position cannot change after initialisation. > There is a special Tuple in Rust called the unit tuple. () represents the unit tuple. It has no values in it. This is what is returned by functions that return "nothing" in Rust. Both Arrays and Tuples can be destructured in Rust. Here are the destructured values for the top score and the general availability of a PS5 from the above examples: ```rust let [my_score, _, _] = top_scores; ``` ```rust let (_, _, is_available) = product; ``` > _ represents a throwaway value that is not assigned and therefore cannot be used. If you didn't know the number of elements in ```top_scores``` and just wanted to get the first one, you could even do this: ```rust let [my_score, ..] = top_scores; ``` > Funnily though, the "rest" operator in Rust is .. and not .... ### A Practical guide to use Arrays and Objects in JavaScript - URL: https://nive.sh/articles/practical-guide-to-use-array-and-objects-in-javascript - Published: Jun 26, 2023 - Reading time: 4 min read - Categories: javascript - Tags: javascript, array, object > JavaScript objects and arrays are fundamental data structures used to organize and store data. In this comprehensive guide, we will explore the concepts of objects and arrays, provide relatable examples for both technical and non-technical individuals, and delve into safe techniques for copying and modifying these data structures. By following the discussed techniques, you can ensure data integrity, avoid unintended side effects, and confidently work with JavaScript data. ## Introduction JavaScript objects and arrays are fundamental data structures used to organize and store data. In this comprehensive guide, we will explore the concepts of objects and arrays, provide relatable examples for both technical and non-technical individuals, and delve into safe techniques for copying and modifying these data structures. By following the discussed techniques, you can ensure data integrity, avoid unintended side effects, and confidently work with JavaScript data. ## Understanding Objects and Arrays Objects and arrays are containers that allow us to group related data together. They provide a way to organize and access information efficiently. Let's take a closer look at each of them with relatable examples. ### Objects An object can be thought of as a real-life item that possesses certain characteristics or attributes. For example, let's consider a person named John. We can represent John as an object with various properties, such as his name, age, and occupation. ```jsx const person = { name: "John", age: 25, occupation: "Software Developer" }; ``` In this example, ```person``` is an object that represents John. The properties (```name```, ````age````, and ```occupation```) describe different aspects of John's identity. ### Arrays An array is like a list—a collection of items in a specific order. Imagine a shopping list with items like apples, bread, and milk. Each item represents an element in the array, and the order of items is crucial. ```jsx const shoppingList = ["apples", "bread", "milk"]; ``` Here, ```shoppingList``` is an array that holds the items we want to buy. The elements are stored in a particular sequence, allowing us to access them based on their position or index. ### Copying and Modifying Arrays Safely To create a copy of an array without modifying the original, we can use safe techniques that preserve the array's structure. **Shallow Copy** A shallow copy creates a new array with references to the same elements. We can achieve this using the ```slice()``` method. ```jsx const originalArray = [1, 2, 3]; const newArray = originalArray.slice(); ``` **Deep Copy** For a deep copy that ensures independence from the original array, even with nested objects or arrays, we can use ```JSON.parse(JSON.stringify(originalArray))```. ```jsx const originalArray = [1, [2, 3], { name: "John" }]; const deepCopyArray = JSON.parse(JSON.stringify(originalArray)); ``` **Updating Arrays Safely** Modifying the copied array won't affect the original, ensuring data integrity. ```jsx const originalArray = [1, 2, 3]; const newArray = originalArray.slice(); newArray[0] = 10; ``` ### Copying and Modifying Objects Safely Copying objects requires caution, as they are assigned by reference. However, we can employ safe techniques to create independent copies. **Shallow Copy** To create a shallow copy of an object, we can use ```Object.assign()``` or the spread operator (```{...}```). ```jsx const originalObject = { name: "John", age: 25 }; const newObject = Object.assign({}, originalObject); // or const newObject = { ...originalObject }; ``` **Deep Copy** For a deep copy, including nested objects, we can use ```JSON.parse(JSON.stringify(originalObject))```. ```jsx const originalObject = { name: "John", data: { age: 25 } }; const deepCopyObject = JSON.parse(JSON.stringify(originalObject)); ``` **Updating Objects Safely** By modifying properties within the copied object, we prevent unintended changes to the original object. ```jsx const originalObject = { name: "John", age: 25 }; const newObject = Object.assign({}, originalObject); newObject.age = 30; ``` ## Conclusion Objects and arrays are essential data structures in JavaScript, facilitating effective organization and management of data. By employing safe techniques for copying and modifying these structures, such as using ```slice()``` for arrays, ```Object.assign()``` or the spread operator for shallow object copies, and ```JSON.parse(JSON.stringify())``` for deep object copies, you can ensure data integrity and avoid unintended side effects. Whether you're a beginner or an experienced developer, understanding and implementing these techniques will empower you to confidently work with JavaScript data structures, maintaining control over your data. ### Hello, Rust! - URL: https://nive.sh/articles/hello-rust - Published: Jun 23, 2023 - Reading time: 3 min read - Categories: JavaScript, Rust - Tags: rust, javascript > Welcome to Rust for JavaScript Developers! It's fantastic to have you here. Let's dive right in. ## Introduction Welcome to Rust for JavaScript Developers! It's fantastic to have you here. Let's dive right in. ## Installation Let's install Rust. If you're on macOS, Linux, or another Unix-like OS, spin up a terminal and enter the following: ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` This will use rustup to install the latest stable version of Rust. > rustup is a tool to install the entire Rust toolchain (including Cargo which we'll talk about later) and lets you switch channels (to nightly versions of Rust for instance if you like living dangerously) Once ```rustup``` is done doing its thing, run ```rustc --version``` to ensure you got everything you need and to see the version of Rust you just installed. ```rustc``` is the Rust compiler by the way. Now, let's write our very first Rust program! Are you ready? Create a file, call it ```hello-rust.rs``` and open it in your favourite editor. Type the following into your brand new ```hello-rust.rs``` file. ```rust fn main() { println!("Hello, Rust!"); } ``` Now, time to compile it. Go back to the terminal and run: ```bash rustc hello-rust.rs ``` Lo and behold, you'll now have a nice little compiled binary in the same directory called ```hello-rust``` which you can run by running: ```bash ./hello-rust ``` This should print out "Hello, Rust!" in your terminal. You did it! Give yourself a pat on the back. You just wrote your first Rust program! Now let's take a deeper look into that syntax. ## Syntax ### Functions To create a function in Rust, you use the ```fn``` keyword. This is just like the ```function``` keyword in JavaScript. The rest is identical syntactically. ```rust fn hola() {} ``` ### Printing ```println!``` as the name suggests is how you print something (with a nice line in the end) to the screen. Much like our dear friend, ```console.log```. One quick difference though. ```println!``` is not a function. It's a macro. We'll learn what those are later but that explains the exclamation mark. Macros are called just like functions but with the additional ```!``` before the parenthesis. ### String literals String literals in Rust (just like JavaScript) live in double quotes. Unlike JavaScript though, you can't use ```", "``` or ``` ` ``` interchangeably so you need to stick with a pair of ```"```. ### Semicolons The final bit of relevant syntax in our Hello, Rust example is that little semicolon. Unlike JavaScript, semicolons in Rust are not optional. Every statement in Rust **must** end with a semicolon. ## Semantics ### main Semantically, the only bit in our example we must talk about is the ```main``` function. Every Rust program needs to have a ```main``` function. That is the entry point to your program and is called when your binary is executed. If this were JavaScript, we would have to call it ourselves. > That was a fun little dip, wasn't it? Go grab a tasty beverage of your choice and let's get into statements and variables next. ### Scalars - URL: https://nive.sh/articles/scalars - Published: Jun 23, 2023 - Reading time: 3 min read - Categories: JavaScript, Rust - Tags: rust, javascript - Series: Hello, Rust! > Rust is a statically typed programming language. This means that all values must have a known type at compile time. So how did we get away without adding annotations in our Hello, Rust example? The Rust compiler is quite excellent at type inference and will often infer types for your values and only ask you to specify a type if it can't. ## Introduction Rust is a statically typed programming language. This means that all values must have a known type at compile time. So how did we get away without adding annotations in our Hello, Rust example? The Rust compiler is quite excellent at type inference and will often infer types for your values and only ask you to specify a type if it can't. Types can be scalar or compound as the programming language linguists would say. There are four primitive scalars in Rust. ## Integers, Floating points, Characters and Boolean Rust has four basic scalar types: integers, floating point numbers, characters and Boolean values. Here is an example of each of these: ```rust fn main() { let is_cool: bool = true; let initial: char = 'S'; let age: u64 = 30; let net_worth: f32 = 2.5; // In Bitcoin of course } ``` A Boolean value can be annotated with the ```bool``` keyword. A ```char``` is a character value which as you can see needs to be quoted with single quotes. Integers can have several types based on whether they are signed or not (meaning if they can have negative values or not) and the number of bits they can store. Signed integer types include ```i8```, ```i16```, ```i32```, ```i64``` and the very large ```i128```! Unsigned types include ```u8```, ```u16```, ```u32```, ```u64``` and ```u128``` (even larger range 😱). Floating point types include only ```f32``` and ```f64```. Since most of us are using 64-bit machines these days, stick to ```u64```, ```i64``` and ```f64``` unless you have a good reason. As you would guess, of course you can do regular Math with these. You cannot do Math between integer and floating point though. Unless you cast them: ```rust fn main() { let price = 129; let tax = 23.22; let total = f64::from(price) + tax; } ``` That ```f64::from``` there is a function on the ```f64``` type. The ```::``` in Rust is much like the dot operator in JavaScript when it comes to types and namespaces. You can print these values using our friendly ```println!``` macro as well. ```rust fn main() { let price = 129; let tax = 23.22; let total = f64::from(price) + tax; println!("{}", total) } ``` In the example above, see the empty ```{}``` in the string literal? The ```println!``` macro will construct the right expression to print with the parameters you pass in. Every ```{}``` stands for one parameter in the order they come in. ```rust fn main() { let price = 129; let tax = 23.22; let total = f64::from(price) + tax; println!("Total: {} + {} = {}", price, tax, total) } ``` This is similar to template literals in JavaScript and how they let you inline values minus the inlining values (they need to be separate parameters to ```println!```). ### Statements and Variables - URL: https://nive.sh/articles/statements-and-variables - Published: Jun 23, 2023 - Reading time: 3 min read - Categories: JavaScript, Rust - Tags: rust, javascript - Series: Hello, Rust! > Code is typically composed of statements. Statements consist of one or more values and operators. Initialising a variable, setting it to the return value of a function call, even calling a macro (like the println macro we saw a while ago) are all examples of statements. ## Introduction In the previous chapter, we wrote our first Rust program. In this one, we'll write several more. Code is typically composed of statements. Statements consist of one or more values and operators. Initialising a variable, setting it to the return value of a function call, even calling a macro (like the ```println``` macro we saw a while ago) are all examples of statements. ## Variables ### let ```rust let name = "Nivesh"; ``` This is a simple statement that creates a new variable called ```name``` and initialises its value to Nivesh. That's what Sid is short for by the way. Every statement in Rust must end with a semicolon. ```let``` might seem familiar from JavaScript but is not the same in Rust. In JavaScript, variables created with ```let``` are mutable by default. This is valid JavaScript. ```javascript function main() { let name = "Nivesh"; name = "Saharan"; } ``` Let's try that in Rust. ```rust fn main() { let name = "Nivesh"; name = "Saharan"; } ``` You should see a message when trying to compile this which says: ```bash error[E0384]: cannot assign twice to immutable variable `name` --> hello-rust.rs:3:5 | 2 | let name = "Nivesh"; | ---- | | | first assignment to `name` | help: consider making this binding mutable: `mut name` 3 | name = "Saharan"; | ^^^^^^^^^^^^ cannot assign twice to immutable variable ``` In Rust, all variables created using let are immutable by default. This means you cannot reassign their value once they've been assigned. That doesn't mean you have to assign them when you declare them. ```rust let name; name = "Saharan"; ``` This is perfectly valid. You just can't assign them more than once. ### mut If you need a variable that is mutable, you use the ```mut``` keyword when declaring the variable. ```rust fn main() { let mut name = "Nivesh"; name = "Saharan"; } ``` The ```name``` variable is now mutable which means you're free to reassign it when you like. ### const Rust also has a ```const``` keyword like JavaScript but again they behave very differently. ```const``` in JavaScript creates a variable with an immutable reference (you can still mutate its value, like pushing to a const Array). In Rust, const creates a compile time constant value. When you have a true constant whose value is known at compile time, you should use ```const```. Let's look at an example. ```rust fn main() { const are_you_cool = true; println!("{}", are_you_cool); } ``` Try compiling and running the code above. You should see the following error from the Rust compiler: ```bash error: missing type for `const` item --> hello-rust.rs:2:11 | 2 | const are_you_cool = true; | ^^^^^^^^^^^^ help: provide a type for the constant: `are_you_cool: bool` error: aborting due to previous error ``` Because values initialised with ```const``` are compile time known constants, Rust will not infer their type for you and you will need to provide a type. Let's do that! ```rust fn main() { const are_you_cool: bool = true; println!("{}", are_you_cool); } ``` This should compile nicely! Now we know two more things: how to type a value in Rust and that you are cool. > Notice that the variable name is snake cased? That's a Rust convention. The Rust people like snake_case for variables but of course it's totally fine to use camelCase. It's a convention, not a rule! ### Create your own token on Ethereum, Polygon or Binance Smart Chain in a minute - URL: https://nive.sh/articles/create-your-own-erc20-token-on-ethereum-polygon-binance-in-a-minute - Published: Nov 21, 2021 - Reading time: 1 min read - Categories: web3, ethereum, polygon, blockchain - Tags: web3, ethereum, polygon, matic, smart contract, blockchain, erc20 > Creating your own token has never been this easy and you can now create your own token without any blockchain programming knowledge in just under a minute. ## Introduction Blockchain is my new favourite thing these days, and I wanted to build something on it that anyone can use without any programming knowledge. So I have created an ERC-20 token creator https://bakemytoken.com that doesn’t require any technical/programming knowledge. You just need to fill some fields and within a few minutes, you have launched your own token. ## Supported Blockchains - [Ethereum](https://bakemytoken.com/ethereum) - [Polygon](https://bakemytoken.com/polygon) - [Binance Smart Chain](https://bakemytoken.com/binance-smart-chain) ## Features - No programming knowledge required - Token contracts are verified automatically - Supports multiple blockchains - Uses Openzeppline smart contracts - Audited and widely used by so many projects ## Ready to create your token? [Click here](https://bakemytoken.com/ethereum) to create your [Ethereum](https://bakemytoken.com/ethereum) token now

[Click here](https://bakemytoken.com/polygon) to create your [Polygon](https://bakemytoken.com/polygon) token now

[Click here](https://bakemytoken.com/binance-smart-chain) to create your [Binance Smart Chain](https://bakemytoken.com/binance-smart-chain) token now

[Click here](https://www.producthunt.com/posts/bake-my-token) to read more about the project on Producthunt. ### Say hello to TypeScript - URL: https://nive.sh/articles/say-hello-to-typescript - Published: Jun 21, 2021 - Reading time: 2 min read - Categories: JavaScript, TypeScript - Tags: javascript, typescript > TypeScript is a superset of JavaScript that has optional typing and compiles to plain JavaScript. Technically its JavaScript with static typing, whenever you want to have it. ## Introduction In short, TypeScript is a superset of JavaScript that has optional typing and compiles to plain JavaScript. In simpler words, TypeScript technically is JavaScript with static typing, whenever you want to have it. ## Installation Installing TypeScript is as simple as running the following command in our Terminal: ```bash npm i -D typescript ``` The above command installs TypeScript as a dev dependency in our project. We can also install it globally using: ```bash npm i -g typescript ``` ## Why TypeScript? There are many reasons why we should use TypeScript but the most important ones are: 1. TypeScript is more reliable 1. TypeScript is more explicit 1. Easier to refactor code without breaking it significantly. 1. TypeScript and JavaScript are practically interchangeable, so why not? ## How to use Once we have TypeScript installed, we can start writing TypeScript files which have the extension `.ts` ```tsx // File: helloWorld.ts const greeting = 'Hello world!'; ``` > We can write any JavaScript code in our TypeScript files and that will be a valid TypeScript code. What TypeScript allows us to do is we can add type definition to our code which then checked to insure we have type safety in our code. ```tsx // File: helloWorld.ts const greeting: string = 'Hello world!'; const year: number = 2021; ``` We cannot directly execute our TypeScript code directly in the browser so we need to compile it down JavaScript first. Our typescript page also gave us access to a TypeScript compiler. If you installed it locally, we can access it as ```bash node_modules/typescript/bin/tsc ``` and can compile our file down to JavaScript ```bash node_modules/typescript/bin/tsc helloWord.ts ``` It will generate a `helloWorld.js` file in our project. Here's what this new file contains: ```jsx // File: helloWorld.js const greeting = 'Hello world!'; const year = 2021; ``` We can also pass some options to our `tsc` command or alternatively create a `tsconfig.json` file in our project. You can learn more about the options [here in official documentation](https://www.typescriptlang.org/docs/handbook/compiler-options.html). > This was just a basic introduction to TypeScript and in the next post, we will learn about different types in TypeScript. ### [Shopify Script] 2 or more variants within the same product ID get 10% off - URL: https://nive.sh/articles/2-or-more-variants-within-the-same-product-get-10-percent-off - Published: Apr 7, 2021 - Reading time: 1 min read - Categories: shopify-scripts, shopify-plus - Tags: shopify, shopify scripts, ruby, shopify plus - Series: Shopify Scripts > In this article, we are going to create a Shopify Script that gives 10% discount on the line items having at least 2 quantities of same product. ## Introduction In this article, we are going to create a Shopify Script that gives 10% discount on the line items having at least 2 quantities of same product. ## Requirements 2 or more variants within the same product ID get 10% off #### Case 1: - Product A Variant 1 - Product A Variant 2 - Product A Variant 3 **Total 10% off** #### Case 2 - Product A Variant 1 - Product A Variant 2 **Total 10% off** #### Case 3 - Product A Variant 1 - Product A Variant 2 - Product B Variant 1 **Only Product A (Variant 1+2) 10% off, not Product B** #### Case 4 - Product A Variant 1 - Product B Variant 1 **No discount** ## Final code ```ruby # Settings DISCOUNT_PERCENTAGE = 10; DISCOUNT_MESSAGE = "Bulk Discount"; MINIMUM_QUANTITIES = 2 # Code starts here products_by_quantity = {}; Input.cart.line_items.each do |line_item| product = line_item.variant.product next if product.gift_card? if products_by_quantity[product.id] products_by_quantity[product.id] += line_item.quantity; else products_by_quantity[product.id] = line_item.quantity; end end Input.cart.line_items.each do |line_item| product = line_item.variant.product next if product.gift_card? if products_by_quantity[product.id] >= MINIMUM_QUANTITIES line_item.change_line_price(line_item.line_price * ((100 - DISCOUNT_PERCENTAGE) / 100), message: DISCOUNT_MESSAGE); end end Output.cart = Input.cart ``` ### Powerful ways to Supercharge your NGINX server and improve its performance - URL: https://nive.sh/articles/powerful-ways-to-supercharge-your-nginx-server-and-improve-its-performance - Published: Aug 7, 2020 - Reading time: 5 min read - Categories: nginx, ssl, optimisations - Tags: optimisation, nginx, ssl, speed optimisation > You don’t need to be a DevOps expert to make the optimizations explained in this post. Anyone who is new to web applications and is using NGINX can use these steps. All you have to do is edit your NGINX config file. ## Introduction You don’t need to be a DevOps expert to make the optimizations explained in this post. Anyone who is new to web applications and is using NGINX can use these steps. All you have to do is edit your NGINX config file. *Screenshot: Lighthouse test result* ## Let's begin ### 1. Improve Performance with `HTTP/2` Support `HTTP/2` has a lot of benefits over `HTTP`, like allowing the browser to download files in parallel, and allowing the server to push resources, among others. All you have to do is to replace `http` with `http2` in your server block. *Screenshot: Use HTTP/2 instead of HTTP* ### 2. Reduce Scrapping/Attacks Limiting the requests to the server is critical, as this can easily deplete the resources and can result in huge billings. It's also important to fend off those who want to scrape and attack the servers. *Screenshot: Reduce Scrapping/Attacks* ### 3. Client-side Caching Caching static files on the browser is easy, and it saves a lot of requests to the server. All you have to do is add these two code blocks and specify the expiration as you please. You can include any other static file extension you deem worthy of caching. *Screenshot: Client-side Caching* ### 4. Microcaching Microcaching is a caching technique in which content is cached for a very short period of time, perhaps as little as 1 second. This effectively means that updates to the site are delayed by no more than a second, which in many cases is perfectly acceptable. *Screenshot: Microcaching* ### 5. Redirect WWW Google prefers that you choose a domain without `www` instead. It’s better to choose the naked domain as its smaller and removes the redundant `www` . You can now redirect all `www` users to your naked domain by adding these below directives. *Screenshot: Redirect WWW* ### 6. Content Compression Here comes `Brotli`, which is the latest encoding algorithm by Google. Brotli is `~20%` more efficient than `Gzip`. Just keep in mind you should send content in `Gzip` where Brotli is not supported. Brotli works best with static files rather than dynamic content. *Screenshot: Content Compression* ### 7. Improve Security NGINX doesn't have all the important security headers required which are pretty straightforward actually. These prevent clickjacking attacks, cross-site scripting attacks, and other code injection attacks. HSTS also protects from protocol downgrade attacks. *Screenshot: Improve Security* ### 8. Optimize SSL and Sessions Use on TLS and disable SSL. SSL is pretty old and outdated and has a lot of vulnerabilities. Optimize cipher suites, as they are the core of TLS. This is where encryption happens. *Screenshot: Optimize SSL and Sessions* ## Final NGINX config and domain config files ### 1. /etc/nginx/sites-available/example.com ``` proxy_cache_path /tmp/cacheapi levels=1:2 keys_zone=microcacheapi:100m max_size=1g inactive=1d use_temp_path=off; server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; server_name example.com; location /api/ { # Rate Limiting limit_req zone=reqlimit burst=20; # Max burst of request limit_req_status 460; # Status to send # Connections Limiting limit_conn connlimit 20; # Number ofdownloads per IP # Bandwidth Limiting limit_rate 4096k; # Speed limit (here is on kb/s) # Micro caching proxy_cache microcacheapi; proxy_cache_valid 200 1s; proxy_cache_use_stale updating; proxy_cache_background_update on; proxy_cache_lock on; proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; } location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location ~* \.(jpg|jpeg|png|gif|ico)$ { expires 30d; } location ~* \.(css|js)$ { expires 7d; } ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot # Pagespeed Module pagespeed on; pagespeed FileCachePath /var/cache/ngx_pagespeed_cache; location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""; } location ~ "^/pagespeed_static/" { } location ~ "^/ngx_pagespeed_beacon$" { } pagespeed RewriteLevel PassThrough; pagespeed EnableCachePurge on; pagespeed PurgeMethod PURGE; pagespeed EnableFilters prioritize_critical_css; } server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; } server { listen 80; listen [::]:80; listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.example.com; return 301 https://example.com$request_uri; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot } ``` ### 2. /etc/nginx/nginx.conf ``` user www-data; worker_processes auto; pid /run/nginx.pid; events { worker_connections 768; # multi_accept on; } http { # Basic Settings sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; # SSL Settings ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GC$ # Optimize session cache ssl_session_cache shared:SSL:50m; ssl_session_timeout 1d; # Enable session tickets ssl_session_tickets off; # OCSP Stapling ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s; resolver_timeout 2s; # security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "script-src 'strict-dynamic' 'nonce-rAnd0m123' 'unsafe-inline' http: https:; object-src 'none'; base-uri 'none';" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; add_header X-Cache-Status $upstream_cache_status; # Logging Settings access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # limits limit_req_log_level warn; limit_req_zone $binary_remote_addr zone=reqlimit:10m rate=10r/m; limit_conn_zone $binary_remote_addr zone=connlimit:100m; limit_conn servers 1000; # Simultaneous Connections include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } ``` ## Bonus (Nginx config file generator tool) If you find this beyond your reach, then there is [this simple website](https://www.digitalocean.com/community/tools/nginx) that can get the final config file for you. > Source: [{`https://twitter.com/1HaKr/status/1291579129112887296`}](https://twitter.com/1HaKr/status/1291579129112887296). ### Different types of Shopify apps - URL: https://nive.sh/articles/types-of-shopify-apps - Published: Jul 17, 2020 - Reading time: 5 min read - Categories: shopify - Tags: shopify, shopify apps, shopify app store, shopify app types, shopify public apps, shopify private apps, shopify custom apps, how to build shopify apps > In this lesson, we will learn about four types (Public, private, custom and draft apps) of Shopify apps and different characteristics for each type of app. ## Introduction Shopify apps are web applications that add functionality to Shopify stores in several different ways: - Reading and writing store data, either in response to user input or [webhook](https://shopify.dev/docs/admin-api/rest/reference/events/webhook) event notifications - Extending new features inside existing parts of the Shopify admin or POS - Enhancing the way stores display information to customers > We host Shopify apps on our own infrastructure. We can host our apps anywhere and can build with any tech stack of our choice. A partners account is required to create and manage all types of apps. ## Types of Shopify apps Depending on the purpose of our app and how we’ll distribute or sell it, we first need to choose what type of app we’ll build. App types can’t be changed after the app has been created, so we must understand the different capabilities and requirements of each type. There are four app types: ### 1. Public Apps Public apps are meant for developers who want to distribute their apps to many merchants. These are the key features of public apps: - They can be installed on multiple Shopify stores - They must go through Shopify’s [app approval process](https://shopify.dev/concepts/app-store/getting-your-app-approved) - We can sell them in the [Shopify App Store](https://shopify.dev/concepts/app-store) - They manage authentication with [OAuth 2.0](https://shopify.dev/concepts/about-apis/authentication) - They’re created and managed in our Partner Dashboard - They can use [Shopify App Bridge](https://shopify.dev/tools/app-bridge) to appear as an [embedded app](https://shopify.dev/concepts/apps#embedded-apps) in the Shopify admin - They can use [app extensions](https://shopify.dev/docs/app-extensions) to extend the Shopify admin UI - They must sync certain customer data with Shopify, as explained in the [API Terms of Use](https://www.shopify.com/legal/api-terms) Every public app that passes Shopify’s approval process has a profile page on the Shopify App Store. We can choose to make our app’s profile page listed or unlisted. Which one we choose depends on our business model and how we want to promote and sell our app. We can change our app’s listing status at any time. #### Types of public apps

1. Listed apps Listed apps are fully visible in Shopify App Store search results and categories: - It has a listing page with a Shopify App Store URL - Merchants can install it from that listing page - Its listing shows up in relevant category pages - Its listing is indexed in App Store search results - Its listing is visible to other search engines - By default, all approved public apps are listed.

2. Unlisted apps Unlisted apps don't appear in Shopify App Store search results or categories. Instead, we can install them from the app's App Store listing or the developer's website. If we don’t want our app to be listed in the Shopify App Store, we can choose to make it unlisted. Being unlisted means our app has limited visibility in the Shopify App Store: - It has a listing page with a Shopify App Store URL - Merchants can install it from that listing page - Its listing does **not** show up in relevant category pages - Its listing is **not** indexed in App Store search results - Its listing is **not** visible to other search engines > Both listed and unlisted apps must pass the Shopify App review process. A listed app is fully visible in the Shopify App Store, but an unlisted app has limited visibility in the Shopify App Store. ### 2. Custom Apps Custom apps are meant for developers building an app tailored for a single merchant. These are the key features of custom apps: - They can be installed on a single Shopify store - They don’t go through Shopify’s app approval process - We can’t sell them in the Shopify App Store - WE can’t use the Billing API to charge merchants for them - They manage authentication with [OAuth 2.0](https://shopify.dev/concepts/about-apis/authentication) - They’re created and managed in our Partner Dashboard - They can use [Shopify App Bridge](https://shopify.dev/tools/app-bridge) to appear as an [embedded app](https://shopify.dev/concepts/apps#embedded-apps) in the Shopify admin - They can use [app extensions](https://shopify.dev/docs/app-extensions) to extend the Shopify admin UI A custom Shopify app can interact with the Shopify API on behalf of a single store. To authenticate with Shopify by using a custom app, we need to generate an [installation link](https://shopify.dev/tutorials/authenticate-a-custom-app-with-oauth#create-a-custom-app-and-generate-an-installation-link) from our Partner Dashboard. The merchant uses the link to go through the OAuth process and install the app on their store. > Custom apps are built exclusively for one Shopify store and aren't listed on the Shopify App Store. ### 3. Private Apps Private apps are meant for developers building an app for a merchant with specific requirements not met by custom apps. These are the key features of private apps: - They’re created for a single Shopify store, or a small group of clients - They don’t go through Shopify’s app approval process - We can’t sell them in the Shopify App Store - Manage authentication with [basic HTTP authentication](https://shopify.dev/concepts/about-apis/authentication) - They’re created and managed in the merchant’s Shopify admin A private Shopify app can interact with the Shopify API on behalf of a single store. To authenticate with Shopify by using a private app, we need to generate the credentials from the Shopify admin and provide these credentials in our request to Shopify. > [Private apps](https://help.shopify.com/en/manual/apps/private-apps) are available only to the store we created it from and aren't listed on the Shopify App Store. We can create a private app for our store in the [Shopify admin](https://www.shopify.com/admin/apps/private). ### 4. Draft apps Draft apps are used by Shopify Partners during development, and can only be installed on development stores for testing purposes. Installing a draft app on a development store [disables store transfer permanently](https://help.shopify.com/en/api/guides/store-transfers#transfer-disabled-stores). > Draft apps can only be installed on other stores after [Shopify review](https://help.shopify.com/api/app-store/getting-your-app-approved/review-process), or once they're converted to a custom app. More information for building apps is available [here](https://shopify.dev/concepts/apps) ### Laravel/Php - How to serve gzipped content from S3 - URL: https://nive.sh/articles/how-to-serve-gzipped-content-from-s3-in-laravel-php - Published: Jun 1, 2020 - Reading time: 2 min read - Categories: laravel, php, mysql, database - Tags: laravel, mysql, database, optimisation, eloquent performance patterns > Until last month, our apps were serving JavaScript files from s3 without any compression and one of our customer asked us if we can enable gzip compression on the assets being served. Until last month, our apps were serving JavaScript files from s3 without any compression and one of our customer asked us if we can enable gzip compression on the assets being served. As much as I researched, I found there is no out of the box gzip compression for the files on Amazon S3, Digital Ocean Spaces or Vultr Objects etc. So I decided to gzip compress the content of file on my server's end and then upload the compressed version to s3. ## Here's what my code looks like now (Laravel Example) ```php $disk = config('filesystems.cloud'); // Returns s3 $settings = $shop->app_settings(); // Returns an array of all the settings $content = view()->make('scripts.settings', compact('settings'))->__toString(); // Loads a view with all the settings $gzippedContent = gzencode($content); // gzip compress the content $fileName = 'settings/' . $shop->domain . '.js'; // Here we upload the file to S3 $response = \Storage::disk($disk)->put($fileName, $content, [ 'visibility' => 'public', 'ContentType' => 'application/javascript', 'ContentEncoding'=> 'gzip', ]); ``` The only thing I had to do was just use a simple Php function `gzencode()` and send `ContentEncoding` along with the put request. > As the result, the file size is now reduced by almost 40% and the app loads way faster than before. ### A Few Quick Terminal Tips - URL: https://nive.sh/articles/few-quick-terminal-tips - Published: May 26, 2020 - Reading time: 1 min read - Categories: shell - Tags: terminal, command line > Few tips for fast & productive work on a terminal... ## Run the Same Command Again ```bash $ !! # Run last executed command $ sudo !! # Run last execute command as sudo $ ! # Run last command starting with a specific word/character ``` ## See A List of All The Commands You’ve Entered ```bash $ history ``` ## Write ASCII art banners ```bash $ banner -w ``` ## Place cursor anywhere in your terminal for current command Hold `option` and `click` where you need your cursor. No need to use `arrow keys` or `option + arrow key` to navigate Source: https://twitter.com/i/status/1264140864751878144 ### A Practical guide to use LocalStorage and SessionStorage - URL: https://nive.sh/articles/practical-guide-to-use-localstorage-and-sessionstorage - Published: May 24, 2020 - Reading time: 3 min read - Categories: javascript - Tags: javascript, storage, local storage, session storage, browser storage > SessionStorage and LocalStorage are a simple key/value pair storage and only the string type of data can be stored. SessionStorage and LocalStorage both has same API. Both storage objects provide same methods and properties. ## SessionStorage `SessionStorage` is a simple key/value pair storage and only the string type of data can be stored. It is a tab specific storage and the data stored in `SessionStorage` will be lost when that tab is closed. We can store upto 5MB of data in this storage. Data stored in `SessionStorage` cannot be accessed from another tab. ## LocalStorage `LocalStorage` is also a simple key/value pair storage and only the string type of data can be stored. The data stored in `LocalStorage` is shared between all tabs for same domain. There is no expirations for the data in `LocalStorage` so it is always there even if you close the tabs or restart your system. ## Check if the browser supports it ```js if(typeof(Storage) !== void(0)) { // Your browser support localStorage and sessionStorage } else{ // Sorry! No web storage support.. } ``` ## Storage API `SessionStorage` and `LocalStorage` both has same API. Both storage objects provide same methods and properties. Following examples shows the API usage for localStorage and since they use same API, feel free to replace `localStorage` with `sessionStorage` ### Store an Item ```jsx // Store a simple string localStorage.setItem('my-key', 'my-value'); // Store an object (Must be converted to string) localStorage.setItem('my-object-key', JSON.stringify({key: 'value'})); ``` ### Get an Item from Storage ```jsx localStorage.getItem('my-key'); // Returns string: 'my-value' localStorage.getItem('my-object-key'); // Returns string: '{"key":"value"}' JSON.parse(localStorage.getItem('my-object-key')); // Returns object: {key:"value"} ``` ### Remove an item ```jsx localStorage.removeItem('my-key'); ``` ### The number of stored items ```jsx localStorage.length // Return count of items stored ``` ### Get the key on a given position ```jsx localStorage.key(0); // Returns key of the item at very first position ``` ### Get all keys ```jsx Object.keys(localStorage); // Returns array of all keys ``` ### Get all items ```jsx for(let i = 0; i < localStorage.length; i++){ const key = localStorage.key(i); const value = localStorage.getItem(key); console.log(key, value) } ``` ### Remove everything from storage ```jsx localStorage.clear(); // Removes everything from localStorage ``` ## Storage Event When the data gets updated in `LocalStorage` or `SessionStorage`, the storage event is triggered with following properties: - `key` - The name of key that was changed. (It will be `null` if `.clear` was called) - `oldValue` - The old value of changed key. (It will be `null` if it is newly added) - `newValue` - The new value of changed key. (It will be `null` if the key was removed) - `url` - The URL where the change happened - `storageArea` - `localStorage` object or `sessionStorage` object depending on where it was updated. > Storage event is triggered on all window objects of same domain excepts the one that triggered it. ### Listen for events ```jsx window.addEventListener('storage', function(e){ console.log(e.key, e.oldValue, e.newValue, e.url, e.storageArea) }); ``` > Storage event triggered when the value is actually changed. Setting same value won't trigger the event. ### Listen for a specific key change ```jsx window.addEventListener('storage', function(e){ if(e.key === 'my-key') { // Do your thing } }); ``` ## Things to remember - `LocalStorage` and `SessionStorage` allow to store key/value (`String` only). - Storage event triggers on `setItem`, `removeItem`, `clear` calls. - The event triggers on all `window` objects where the storage is accessible, except the one that caused it. - Refreshing the page doesn't remove data from `SessionStorage` - Closing the browser or rebooting your system doesn't remove data from `LocalStorage` - Do not store sensitive user information in `LocalStorage` or `SessionStorage` ### A Practical guide to use Fetch API - URL: https://nive.sh/articles/practical-guide-to-use-fetch-api - Published: May 23, 2020 - Reading time: 3 min read - Categories: javascript - Tags: javascript, fetch, ajax > Fetch is a promise based Javascript API for making asynchronous HTTP requests. It is a clean, simple, powerful and a flexible API to get/send data from/to a server. ## Introduction Fetch is a promise based Javascript API for making asynchronous HTTP requests. It is a clean, simple, powerful and a flexible API to get/send data from/to a server. ## A simple GET request example using Fetch API ```jsx fetch('https://jsonplaceholder.typicode.com/posts') .then(function(response) { // }) .catch(function(error) { // }); ``` The Response returned by the fetch() method contains the information about the request and the response of the network request including headers, status code, and status message. The body of Response has a few methods: - **clone()** - As the method implies this method creates a clone of the response. - **redirect()** - This method creates a new response but with a different URL. - **arrayBuffer()** - In here we return a promise that resolves with an ArrayBuffer. - **formData()** - Also returns a promise but one that resolves with FormData object. - **blob()** - This is one resolves with a Blob. - **text()** - In this case it resolves with a string. - **json()** - Lastly we have the method to that resolves the promise with JSON. ```jsx fetch('https://jsonplaceholder.typicode.com/posts') .then(function(response) { // get response headers console.log(response.headers.get('content-type')); console.log(response.headers.get('expires')); // HTTP response status code console.log(response.status); // shorthand for `status` between 200 and 299 console.log(response.ok); // status message of the response e.g. `OK` console.log(response.statusText); // check if there was a redirect console.log(response.redirected); // get the response type (e.g., `basic`, `cors`) console.log(response.type); // the full path of the resource console.log(response.url); }) .catch(function(error) { // }); ``` Here is how you can use Fetch to request JSON data from server: ```jsx fetch('https://jsonplaceholder.typicode.com/posts') .then(function(response){ return response.json(); }) .then(function(data) { // data here is JSON object console.log(data); }) .catch(function(error) { // }); ``` ## How to use Fetch API to send POST requests Fetch is not just for GET requests. It can be used for all other request types like POST, PUT, PATCH, DELETE etc. Here's an example of POST type request: ```jsx fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', body: JSON.stringify({ title: 'foo', body: 'bar', userId: 1 }) }) .then(function(response){ return response.json(); }) .then(function(data) { // data here is JSON object }) .catch(function(error) { // }); ``` > Make sure you Stringify your JSON data before sending to server. ## Set Headers for Fetch request Setting up headers for your request is pretty easy. One of the easiest way is to pass a headers objects along with the request. ```jsx fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', body: JSON.stringify({ title: 'foo', body: 'bar', userId: 1 }), headers: { "Content-type": "application/json" } }) .then(function(response){ return response.json(); }) .then(function(data) { // data here is JSON object }) .catch(function(error) { // }); ``` ## Cookies Fetch doesn't send cookies by default and if you need to send cookies along with the request, you will have to enable it explicitly. Here's how: ```jsx fetch('https://jsonplaceholder.typicode.com/posts', { credentials: 'include' }) .then(function(response) { // }) .catch(function(error) { // }); ``` ## Error Handling We can use the catch() method of the promise to intercept any error that is thrown during the execution of the request. However, no error will be thrown if the request hits the server and comes back, regardless of what response was returned by the server. The promise returned by the fetch() doesn't reject HTTP errors even if the HTTP response code is 404 or 500. ```jsx fetch('https://jsonplaceholder.typicode.com/some-invalid-path', { credentials: 'include' }) .then(function(response) { if(response.ok) { return response.json(); } return Promise.reject(response.status); }) .catch(function(error) { // console.error(error) }); ``` ### A better approach to keep Laravel .env files for multiple environments - URL: https://nive.sh/articles/better-approach-to-keep-env-files-for-multiple-environments - Published: May 22, 2020 - Reading time: 2 min read - Categories: laravel - Tags: laravel, environment > Laravel comes with a .env file by default and it is called .env.example and we create a copy of .env.example file as .env... ## Introduction Laravel comes with a `.env` file by default and it is called `.env.example` and we create a copy of `.env.example` file as `.env` `.env.example` should not be in `.gitignore` as it is to be used as an example environment file for you and your team. You must add all new environment variables that you add in `.env` file to `.env.example` file as well so your team can be in sync with what variables are required for this project to run. Now let's say if you need to make copy of .env.example for several environments i.e. development, staging, production the approach I use to name those files are as below: - `.env.development.env` - `.env.staging.env` - `.env.production.env` One of the benefit of doing this is we get syntax highlighting in IDEs like PhpStorm or editors like Visual Studio Code. ## How to add `.env` files to `.gitignore` We should have all our custom `.env` files in `.gitignore` file at the root of our project so we don't accidentally push them to Github or any other platform via git. Here's an example of a basic `.gitignore` file: ``` ## Laravel's default .gitignore /node_modules /public/hot /public/storage /storage/*.key /vendor .env .env.backup .phpunit.result.cache Homestead.json Homestead.yaml npm-debug.log yarn-error.log ## Custom added files *.env # It will cover all your custom env files with .env extension ``` ## A gentle reminder Do not use `env()` helper in your project anywhere outside of config files. Using `config()` instead of `env()` is super important when you enable caching! ### My Nginx configurations for Virtual Host, SSL etc. - URL: https://nive.sh/articles/my-nginx-configurations-for-virtual-host-ssl-etc - Published: Apr 14, 2020 - Reading time: 2 min read - Categories: server, laravel - Tags: nginx, virual hosts, ssl, laravel, domain > Here are my configurations I use for my Laravel apps. Hope someone find these useful. Here are my configurations I use for my Laravel apps. Hope someone find these useful. ## Virtual Host ``` # /etc/nginx/sites-available/{{domain}}.conf server { listen 80; listen [::]:80; server_name www.{{domain}} {{domain}}; include snippets/letsencrypt.conf; return 301 https://{{domain}}$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.{{domain}}; ssl_certificate /etc/letsencrypt/live/{{domain}}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{domain}}/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/{{domain}}/fullchain.pem; include snippets/ssl-params.conf; return 301 https://{{domain}}$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; index index.php; server_name {{domain}}; root {{deploy_path}}/current/public; client_max_body_size 100m; access_log "/var/log/nginx/{{application}}nginx_access.log"; error_log "/var/log/nginx/{{application}}nginx_error.log"; # check file exist and send request sting to index.php location / { try_files $uri $uri/ /index.php?$args; } # allow execute all php files location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; fastcgi_intercept_errors off; fastcgi_buffer_size 16k; fastcgi_buffers 4 16k; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; } # disallow access to apache configs location ~ /\.ht { deny all; } # disallow access to git configs path location ~ /\.git { deny all; } ssl_certificate /etc/letsencrypt/live/{{domain}}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{domain}}/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/{{domain}}/fullchain.pem; include snippets/ssl-params.conf; } # sudo ln -s /etc/nginx/sites-available/{{domain}}.conf /etc/nginx/sites-enabled/{{domain}}.conf ``` ### Let's encrypt ``` # /etc/nginx/snippets/ssl-params.conf location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/letsencrypt; } ``` ``` # /etc/nginx/snippets/ssl-params.conf ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; #ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; #add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; ``` P.S. Suggestions/changes are welcome