Giter Club home page Giter Club logo

shopify-app-template-ruby's Introduction

Shopify App Template - Ruby

This is a template for building a Shopify app using Ruby on Rails and React. It contains the basics for building a Shopify app.

Rather than cloning this repo, you can use your preferred package manager and the Shopify CLI with these steps.

Benefits

Shopify apps are built on a variety of Shopify tools to create a great merchant experience. The create an app tutorial in our developer documentation will guide you through creating a Shopify app using this template.

The Ruby app template comes with the following out-of-the-box functionality:

  • OAuth: Installing the app and granting permissions
  • GraphQL Admin API: Querying or mutating Shopify admin data
  • REST Admin API: Resource classes to interact with the API
  • Shopify-specific tooling:
    • AppBridge
    • Polaris
    • Webhooks

Tech Stack

These third party tools are complemented by Shopify specific tools to ease app development:

Tool Usage
Shopify App Rails engine to help build Shopify app using Rails conventions. Helps to install your application on shops, and provides tools for:
  • OAuth
  • Session Storage
  • Webhook Processing
  • etc.
  • ShopifyAPI Gem A lightweight gem to provide tools for:
  • Obtaining an active session. (ShopifyApp uses this behind the scenes to handle OAuth)
  • Clients to make request to Shopify GraphQL and Rest APIs. See how it's used here
  • Error handling
  • Application Logger
  • Webhook Management
  • App Bridge,
    App Bridge React
    Frontend library that:
  • Add authentication to API requests in the frontend
  • Renders components outside of the App’s iFrame in Shopify's Admin page
  • Custom React hooks Custom React hooks that uses App Bridge to make authenticated requests to the Admin API.
    Polaris React A powerful design system and react component library that helps developers build high quality, consistent experiences for Shopify merchants.
    File-based routing Tool makes creating new pages easier.
    @shopify/i18next-shopify A plugin for i18next that allows translation files to follow the same JSON schema used by Shopify app extensions and themes.

    This template combines a number of third party open source tools:

    Getting started

    Requirements

    1. You must create a Shopify partner account if you don’t have one.
    2. You must create a store for testing if you don't have one, either a development store or a Shopify Plus sandbox store.
    3. You must have Ruby installed.
    4. You must have Bundler installed.
    5. You must have Node.js installed.

    Installing the template

    This template runs on Shopify CLI 3.0, which is a node package that can be included in projects. You can install it using your preferred Node.js package manager:

    Using yarn:

    yarn create @shopify/app --template=ruby

    Using npx:

    npm init @shopify/app@latest -- --template=ruby

    Using pnpm:

    pnpm create @shopify/app@latest --template=ruby

    This will clone the template and install the CLI in that project.

    Setting up your Rails app

    Once the Shopify CLI clones the repo, you will be able to run commands on your app. However, the CLI will not manage your Ruby dependencies automatically, so you will need to go through some steps to be able to run your app. To make the process easier, the template provides a script to run the necessary steps:

    1. Start off by switching to the web folder:
      cd web
    2. Install the ruby dependencies:
      bundle install
    3. Run the Rails template script. It will guide you through setting up your database and set up the necessary keys for encrypted credentials.
      bin/rails app:template LOCATION=./template.rb

    And your Rails app is ready to run! You can now switch back to your app's root folder to continue:

    cd ..

    Local Development

    The Shopify CLI connects to an app in your Partners dashboard. It provides environment variables, runs commands in parallel, and updates application URLs for easier development.

    You can develop locally using your preferred Node.js package manager. Run one of the following commands from the root of your app:

    Using yarn:

    yarn dev

    Using npm:

    npm run dev

    Using pnpm:

    pnpm run dev

    Open the URL generated in your console. Once you grant permission to the app, you can start development.

    Deployment

    Application Storage

    This template uses Rails' ActiveRecord framework to store Shopify session data. It provides migrations to create the necessary tables in your database, and it stores and loads session data from them.

    The database that works best for you depends on the data your app needs and how it is queried. You can run your database of choice on a server yourself or host it with a SaaS company. Once you decide which database to use, you can configure your app to connect to it, and this template will start using that database for session storage.

    Build

    The frontend is a single page React app. It requires the SHOPIFY_API_KEY environment variable, which you can get by running yarn run info --web-env. The CLI will set up the necessary environment variables for the build if you run its build command from your app's root:

    Using yarn in your app's root folder:

    yarn build --api-key=REPLACE_ME

    Using npm:

    npm run build -- --api-key=REPLACE_ME

    Using pnpm:

    pnpm run build --api-key=REPLACE_ME

    The app build command will build both the frontend and backend when running as above. If you're manually building (for instance when deploying the web folder to production), you'll need to build both of them:

    cd web/frontend
    SHOPIFY_API_KEY=REPLACE_ME yarn build
    cd ..
    rake build:all

    Making your first API call

    You can use the ShopifyAPI gem to start make authenticated Shopify API calls.

    Examples from this app template:

    • Making Admin GraphQL API request to create products:
      • ProductCreator#create (web/app/services/product_creator.rb)
    • Making Admin Rest API request to count products:
      • ProductsController#count (web/app/controllers/products_controller.rb)

    Hosting

    When you're ready to set up your app in production, you can follow our deployment documentation to host your app on a cloud provider like Heroku or Fly.io.

    When you reach the step for setting up environment variables, you also need to set the following variables:

    Variable Secret? Required Value Description
    RAILS_MASTER_KEY Yes Yes string Use value from web/config/master.key or create a new one.
    RAILS_ENV Yes "production"
    RAILS_SERVE_STATIC_FILES Yes 1 Tells rails to serve the React app from the public folder.
    RAILS_LOG_TO_STDOUT 1 Tells rails to print out logs.

    Known issues

    Hot module replacement and Firefox

    When running the app with the CLI in development mode on Firefox, you might see your app constantly reloading when you access it. That happened in previous versions of the CLI, because of the way HMR websocket requests work.

    We fixed this issue with v3.4.0 of the CLI, so after updating it, you can make the following changes to your app's web/frontend/vite.config.js file:

    1. Change the definition hmrConfig object to be:

      const host = process.env.HOST
        ? process.env.HOST.replace(/https?:\/\//, "")
        : "localhost";
      
      let hmrConfig;
      if (host === "localhost") {
        hmrConfig = {
          protocol: "ws",
          host: "localhost",
          port: 64999,
          clientPort: 64999,
        };
      } else {
        hmrConfig = {
          protocol: "wss",
          host: host,
          port: process.env.FRONTEND_PORT,
          clientPort: 443,
        };
      }
    2. Change the server.host setting in the configs to "localhost":

      server: {
        host: "localhost",
        ...

    I can't get past the ngrok "Visit site" page

    When you’re previewing your app or extension, you might see an ngrok interstitial page with a warning:

    You are about to visit <id>.ngrok.io: Visit Site
    

    If you click the Visit Site button, but continue to see this page, then you should run dev using an alternate tunnel URL that you run using tunneling software. We've validated that Cloudflare Tunnel works with this template.

    To do that, you can install the cloudflared CLI tool, and run:

    # Note that you can also use a different port
    cloudflared tunnel --url http://localhost:3000

    In a different terminal window, navigate to your app's root and call:

    # Using yarn
    yarn dev --tunnel-url https://tunnel-url:3000
    # or using npm
    npm run dev --tunnel-url https://tunnel-url:3000
    # or using pnpm
    pnpm dev --tunnel-url https://tunnel-url:3000

    I'm seeing "App couldn't be loaded" error due to browser cookies

    Using yarn:

    yarn dev --reset

    Using npm:

    npm run dev -- --reset

    Using pnpm:

    pnpm run dev --reset

    Developer resources

    shopify-app-template-ruby's People

    Contributors

    alvaro-shopify avatar amcaplan avatar byrichardpowell avatar cursedcoder avatar elanalynn avatar gcaprio avatar gonzaloriestra avatar hheyhhay avatar isaacroldan avatar klenotiw avatar lizkenyon avatar local-administrator avatar mkevinosullivan avatar mllemango avatar nelsonwittwer avatar paulomarg avatar pbojinov avatar pepicrft avatar rachel-carvalho avatar raphox avatar trishrempel avatar yann120 avatar zzooeeyy avatar

    Stargazers

     avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

    Watchers

     avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

    shopify-app-template-ruby's Issues

    Add up debugger statement to ruby template

    Issue summary

    Hello all, Is there anyway pause in an interactive ruby shell with debugger (or binding.pry or byebug) when running an app with Shopify CLI 3.0
    Running the app with npm run dev, creates two processes with Vite (frontend and backend) I see all the logs.
    When I put a debugger in a ruby file, it does stop the execution at that point but I can't interact with it as I'm seeing logs. I wish to interact at that point. How can this be achieved ?
    Thank you!

    image

    Heroku Deployment not working with initial build

    Issue summary

    I followed all the step for deployment on both Heroku and fly.io, but get the same error for build failing. Again no changes added only checking if production deployment works with template.

    Expected behavior

    What do you think should happen?
    It should deploy with no issues.

    Actual behavior

    What actually happens?
    Build errors occur on Heroku deployment. Error message: An error occurred while installing openssl (3.0.1), and Bundler cannot continue.

    Gemfile:

    # frozen_string_literal: true
    
    source "https://rubygems.org"
    git_source(:github) { |repo| "https://github.com/#{repo}.git" }
    
    ruby "3.1.2"
    
    # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
    gem "rails", "~> 7.0.3"
    
    # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
    gem "sprockets-rails"
    
    # Use sqlite3 as the database for Active Record
    gem "sqlite3", "~> 1.4"
    
    # Use the Puma web server [https://github.com/puma/puma]
    gem "puma", "~> 5.0"
    
    # Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
    gem "importmap-rails"
    
    # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
    gem "turbo-rails"
    
    # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
    gem "stimulus-rails"
    
    # Build JSON APIs with ease [https://github.com/rails/jbuilder]
    gem "jbuilder"
    
    # Use Redis adapter to run Action Cable in production
    gem "redis", "~> 4.0"
    
    # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
    # gem "kredis"
    
    # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
    # gem "bcrypt", "~> 3.1.7"
    
    gem "tzinfo-data"
    
    # Reduces boot times through caching; required in config/boot.rb
    gem "bootsnap", require: false
    
    # Use Sass to process CSS
    # gem "sassc-rails"
    
    # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
    # gem "image_processing", "~> 1.2"
    
    group :development, :test do
      # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
      gem "debug", platforms: [:mri, :mingw, :x64_mingw]
    end
    
    group :development do
      # Use console on exceptions pages [https://github.com/rails/web-console]
      gem "web-console"
    
      # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
      # gem "rack-mini-profiler"
    
      # Speed up commands on slow machines / big apps [https://github.com/rails/spring]
      # gem "spring"
    
      gem "rubocop"
      gem "rubocop-shopify"
    end
    
    group :test do
      # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
      gem "capybara"
      gem "selenium-webdriver"
      gem "webdrivers"
    end
    
    gem "shopify_app", "~> 20.1"
    

    Dockerfile:

    FROM ruby:3.1-alpine
    
    ARG SHOPIFY_API_KEY
    ENV SHOPIFY_API_KEY=$SHOPIFY_API_KEY
    
    RUN apk update && apk add nodejs npm git build-base sqlite-dev gcompat bash
    WORKDIR /app
    
    COPY web .
    
    RUN cd frontend && npm install
    RUN bundle install
    
    RUN cd frontend && npm run build
    RUN rake build:all
    
    COPY entrypoint.sh /usr/bin/
    RUN chmod +x /usr/bin/entrypoint.sh
    
    ENTRYPOINT ["entrypoint.sh"]
    

    Error Output:

    remote: Installing turbo-rails 1.1.1
    remote: Fetching web-console 4.2.0
    remote: Installing web-console 4.2.0
    remote: Fetching rails 7.0.4
    remote: Installing rails 7.0.4
    remote: Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
    remote: 
    remote:     current directory: /usr/local/bundle/gems/openssl-3.0.1/ext/openssl
    remote: /usr/local/bin/ruby -I /usr/local/lib/ruby/3.1.0 -r
    remote: ./siteconf20220912-1-rorgd8.rb extconf.rb
    remote: checking for rb_io_maybe_wait()... yes
    remote: checking for t_open() in -lnsl... no
    remote: checking for socket() in -lsocket... no
    remote: checking for openssl/ssl.h... no
    remote: *** extconf.rb failed ***
    remote: Could not create Makefile due to some reason, probably lack of necessary
    remote: libraries and/or headers.  Check the mkmf.log file for more details.  You may
    remote: need configuration options.
    remote: 
    remote: Provided configuration options:
    remote:         --with-opt-dir
    remote:         --without-opt-dir
    remote:         --with-opt-include
    remote:         --without-opt-include=${opt-dir}/include
    remote:         --with-opt-lib
    remote:         --without-opt-lib=${opt-dir}/lib
    remote:         --with-make-prog
    remote:         --without-make-prog
    remote:         --srcdir=.
    remote:         --curdir
    remote:         --ruby=/usr/local/bin/$(RUBY_BASE_NAME)
    remote:         --with-openssl-dir
    remote:         --without-openssl-dir
    remote:         --with-openssl-include
    remote:         --without-openssl-include=${openssl-dir}/include
    remote:         --with-openssl-lib
    remote:         --without-openssl-lib=${openssl-dir}/lib
    remote:         --with-kerberos-dir
    remote:         --without-kerberos-dir
    remote:         --with-kerberos-include
    remote:         --without-kerberos-include=${kerberos-dir}/include
    remote:         --with-kerberos-lib
    remote:         --without-kerberos-lib=${kerberos-dir}/lib
    remote:         --with-debug
    remote:         --without-debug
    remote:         --enable-debug
    remote:         --disable-debug
    remote:         --with-nsl-dir
    remote:         --without-nsl-dir
    remote:         --with-nsl-include
    remote:         --without-nsl-include=${nsl-dir}/include
    remote:         --with-nsl-lib
    remote:         --without-nsl-lib=${nsl-dir}/lib
    remote:         --with-nsllib
    remote:         --without-nsllib
    remote:         --with-socket-dir
    remote:         --without-socket-dir
    remote:         --with-socket-include
    remote:         --without-socket-include=${socket-dir}/include
    remote:         --with-socket-lib
    remote:         --without-socket-lib=${socket-dir}/lib
    remote:         --with-socketlib
    remote:         --without-socketlib
    remote:         --with-openssl-config
    remote:         --without-openssl-config
    remote:         --with-pkg-config
    remote:         --without-pkg-config
    remote: extconf.rb:100:in `<main>': OpenSSL library could not be found. You might want
    remote: to use --with-openssl-dir=<dir> option to specify the prefix where OpenSSL is
    remote: installed. (RuntimeError)
    remote: 
    remote: To see why this extension failed to compile, please check the mkmf.log which can
    remote: be found here:
    remote: 
    remote:   /usr/local/bundle/extensions/x86_64-linux-musl/3.1.0/openssl-3.0.1/mkmf.log
    remote: 
    remote: extconf failed, exit code 1
    remote: 
    remote: Gem files will remain installed in /usr/local/bundle/gems/openssl-3.0.1 for
    remote: inspection.
    remote: Results logged to
    remote: /usr/local/bundle/extensions/x86_64-linux-musl/3.1.0/openssl-3.0.1/gem_make.out
    remote: 
    remote:   /usr/local/lib/ruby/3.1.0/rubygems/ext/builder.rb:95:in `run'
    remote: /usr/local/lib/ruby/3.1.0/rubygems/ext/ext_conf_builder.rb:47:in `block in
    remote: build'
    remote:   /usr/local/lib/ruby/3.1.0/tempfile.rb:317:in `open'
    remote:   /usr/local/lib/ruby/3.1.0/rubygems/ext/ext_conf_builder.rb:26:in `build'
    remote:   /usr/local/lib/ruby/3.1.0/rubygems/ext/builder.rb:161:in `build_extension'
    remote: /usr/local/lib/ruby/3.1.0/rubygems/ext/builder.rb:195:in `block in
    remote: build_extensions'
    remote:   /usr/local/lib/ruby/3.1.0/rubygems/ext/builder.rb:192:in `each'
    remote:   /usr/local/lib/ruby/3.1.0/rubygems/ext/builder.rb:192:in `build_extensions'
    remote:   /usr/local/lib/ruby/3.1.0/rubygems/installer.rb:853:in `build_extensions'
    remote: /usr/local/lib/ruby/3.1.0/bundler/rubygems_gem_installer.rb:71:in
    remote: `build_extensions'
    remote:   /usr/local/lib/ruby/3.1.0/bundler/rubygems_gem_installer.rb:28:in `install'
    remote:   /usr/local/lib/ruby/3.1.0/bundler/source/rubygems.rb:204:in `install'
    remote:   /usr/local/lib/ruby/3.1.0/bundler/installer/gem_installer.rb:54:in `install'
    remote: /usr/local/lib/ruby/3.1.0/bundler/installer/gem_installer.rb:16:in
    remote: `install_from_spec'
    remote: /usr/local/lib/ruby/3.1.0/bundler/installer/parallel_installer.rb:186:in
    remote: `do_install'
    remote: /usr/local/lib/ruby/3.1.0/bundler/installer/parallel_installer.rb:177:in
    remote: `block in worker_pool'
    remote:   /usr/local/lib/ruby/3.1.0/bundler/worker.rb:62:in `apply_func'
    remote:   /usr/local/lib/ruby/3.1.0/bundler/worker.rb:57:in `block in process_queue'
    remote:   /usr/local/lib/ruby/3.1.0/bundler/worker.rb:54:in `loop'
    remote:   /usr/local/lib/ruby/3.1.0/bundler/worker.rb:54:in `process_queue'
    remote: /usr/local/lib/ruby/3.1.0/bundler/worker.rb:91:in `block (2 levels) in
    remote: create_threads'
    remote: 
    remote: An error occurred while installing openssl (3.0.1), and Bundler cannot continue.
    remote: 
    remote: In Gemfile:
    remote:   shopify_app was resolved to 20.1.1, which depends on
    remote:     shopify_api was resolved to 11.1.0, which depends on
    remote:       openssl
    remote: The command '/bin/sh -c bundle install' returned a non-zero code: 5
    remote: 
    remote: Verifying deploy...
    remote: 
    remote: !       Push rejected to shopify-heroku-test.
    remote: 
    To https://git.heroku.com/shopify-heroku-test.git
     ! [remote rejected] main -> main (pre-receive hook declined)
    error: failed to push some refs to 'https://git.heroku.com/shopify-heroku-test.git'
    
    

    Typescript support?

    Overview/summary

    Does this template support typescript? I've noticed the generated JS is just JS and I didn't notice any options during set up to use typescript.
    ...

    Motivation

    What inspired this enhancement?

    Typescript is widely used, particularly for projects that use React, vite, GraphQL, etc.

    Area

    • [ ✅] Add any relevant Area: <area> labels to this issue

    Checklist

    • [✅ ] I have described this enhancement in a way that is actionable (if possible)

    Connection error when switching to postgres for production database

    Issue summary

    Switching to postgresql for the production database on Heroku, getting error when trying to connect with container setup

    Expected behavior

    Postgres database connection should happen without issue.

    Actual behavior

    After git push heroku main get error when app is trying to connect to database.

    We could not find your database: postgres. Which can be found in the database configuration file located at config/database.yml.
    
    To resolve this issue:
    
    - Did you create the database for this app, or delete it? You may need to create your database.
    - Has the database name changed? Check your database.yml config has the correct database name.
    
    To create your database, run:
    
    bin/rails db:create
    Couldn't create 'ddu5jissp0hjqi' database. Please check your configuration.
    rails aborted!
    ActiveRecord::NoDatabaseError: We could not find your database: postgres. Which can be found in the database configuration file located at config/database.yml.
    
    To resolve this issue:
    
    - Did you create the database for this app, or delete it? You may need to create your database.
    - Has the database name changed? Check your database.yml config has the correct database name.
    
    To create your database, run:
    
    bin/rails db:create
    
    
    Caused by:
    PG::ConnectionBad: connection to server at "3.214.2.141", port 5432 failed: FATAL:  permission denied for database "postgres"
    DETAIL:  User does not have CONNECT privilege.
    

    Steps to reproduce the problem

    Make web/config/database.yml use postgresql adapter.

    default: &default
      adapter: postgresql
      pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
      timeout: 5000
    
    development:
      <<: *default
      database: development_database
    
    # Warning: The database defined as "test" will be erased and
    # re-generated from your development database when you run "rake".
    # Do not set this db to the same as development or production.
    test:
      <<: *default
      database: test_database
    
    production:
      <<: *default
      url: <%= ENV['DATABASE_URL'] %>
    

    Include add-on heroku addons:create heroku-postgresql:hobby-dev

    Add postgresql packages to Dockerfile

    rails production not serve assets

    Issue summary

    Before opening this issue, I have:

    • Upgraded to the latest version of the package
      • shopify_api version: 13.4.0
      • shopify_app version: 21.10.0
      • Rails 7.0.8.1
      • Ruby version: 3.2.2
      • Operating system: Ubuntu 20.04.6 LTS
    • Set log_level: :debug in my configuration, if applicable
    • Found a reliable way to reproduce the problem that indicates it's a problem with the package
    • Looked for similar issues in this repository
    • Checked that this isn't an issue with a Shopify API

    Expected behavior

    What do you think should happen?
    The precompiled assets are served through Cloudflare tunnel

    Actual behavior

    What actually happens?

    When the rails app is run in production all assets return a 404 error
    https://centers-explains-regarding-resulting.trycloudflare.com/assets/index-b0bf1819.js
    https://centers-explains-regarding-resulting.trycloudflare.com/assets/index-f14d2172.css

    Steps to reproduce the problem

    1. be sure assets files are compiled and present in public/assets aka public/assets/index-b0bf1819.js
    2. run rails app in production mode bin/rails server -e production
    3. set ENV as in shopify docs
      RAILS_ENV="production"
      RAILS_SERVE_STATIC_FILES=1
      RAILS_LOG_TO_STDOUT=1

    Debug logs

    09:14:34 │ graphiql │ GraphiQL server started on port 3457
    09:14:34 │ web-frontend │
    09:14:34 │ web-frontend │ > [email protected] dev
    09:14:34 │ web-frontend │ > vite
    09:14:34 │ web-frontend │
    09:14:35 │ web-backend │ => Booting Puma
    09:14:35 │ web-backend │ => Rails 7.0.8.1 application starting in production
    09:14:35 │ web-backend │ => Run bin/rails server --help for more startup options
    09:14:35 │ web-frontend │
    09:14:35 │ web-frontend │ VITE v4.5.2 ready in 698 ms
    09:14:35 │ web-frontend │
    09:14:35 │ web-frontend │ ➜ Local: http://localhost:41661/
    09:14:36 │ web-backend │ D, [2024-03-28T09:14:35.723904 #1248051] DEBUG -- : [dotenv] Set RAILS_MASTER_KEY, SHOPIFY_TEST_CHARGES,
    SECRET_KEY_BASE, RAILS_SERVE_STATIC_FILES, and RAILS_LOG_TO_STDOUT
    09:14:36 │ web-backend │ I, [2024-03-28T09:14:35.723982 #1248051] INFO -- : [dotenv] Loaded .env
    09:14:36 │ web-backend │ I, [2024-03-28T09:14:35.724002 #1248051] INFO -- : [dotenv] Loaded .env
    09:14:36 │ web-backend │ Puma starting in single mode...
    09:14:36 │ web-backend │ * Puma version: 6.4.2 (ruby 3.2.2-p53) ("The Eagle of Durango")
    09:14:36 │ web-backend │ * Min threads: 5
    09:14:36 │ web-backend │ * Max threads: 5
    09:14:36 │ web-backend │ * Environment: production
    09:14:36 │ web-backend │ * PID: 1248051
    09:14:36 │ web-backend │ * Listening on http://127.0.0.1:34241
    09:14:36 │ web-backend │ Use Ctrl-C to stop
    09:14:46 │ web-backend │ I, [2024-03-28T09:14:46.321950 #1248051] INFO -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] Started GET
    "/?embedded=1&hmac=50e646bedbb3bd12be6b10&host=&id_
    token=[FILTERED]&locale=en-US&session=9588f945c42bde137d04f9ac8399f66a215d8378fd58ece4c8ba2fb7c709d971&shop=.myshopify.com&time
    stamp=1711617284" for ** at 2024-03-28 09:14:46 +0000
    09:14:46 │ web-backend │ I, [2024-03-28T09:14:46.324397 #1248051] INFO -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] Processing by
    HomeController#index as HTML
    09:14:46 │ web-backend │ I, [2024-03-28T09:14:46.324483 #1248051] INFO -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] Parameters:
    {"embedded"=>"1", "hmac"=>"50e646bedbb3bd12be6b10",
    "host"=>"
    ", "id_token"=>"[FILTERED]", "locale"=>"en-US",
    "session"=>"9588f945c42bde137d04f9ac8399f66a215d8378fd58ece4c8ba2fb7c709d971", "shop"=>"
    .myshopify.com",
    "timestamp"=>"1711617284"}
    09:14:46 │ web-backend │ D, [2024-03-28T09:14:46.422194 #1248051] DEBUG -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] Shop Load
    (0.2ms) SELECT shops.* FROM shops WHERE shops.shopify_domain = '.myshopify.com' LIMIT 1
    09:14:46 │ web-backend │ D, [2024-03-28T09:14:46.445291 #1248051] DEBUG -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] CACHE Shop
    Load (0.0ms) SELECT shops.
    FROM shops WHERE shops.shopify_domain = '*.myshopify.com' LIMIT 1
    09:14:46 │ web-backend │ D, [2024-03-28T09:14:46.447872 #1248051] DEBUG -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] Rendering
    text template
    09:14:46 │ web-backend │ I, [2024-03-28T09:14:46.447999 #1248051] INFO -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] Rendered text
    template (Duration: 0.0ms | Allocations: 7)
    09:14:46 │ web-backend │ I, [2024-03-28T09:14:46.457121 #1248051] INFO -- : [dc71fbcb-eb0f-4f75-acc3-14d227ad47df] Completed 200
    OK in 133ms (Views: 1.6ms | ActiveRecord: 8.2ms | Allocations: 71766)

    // Paste any relevant logs here
    

    consola

    Same app works fine in rails dev mode bin/rails server -e development

    Shopify Ruby Template , APP_UNINSTALLED Webhook Delivery Failed, Can't Verify CSRF Token.

    Issue summary

    App Uninstalled webhooks delivery failed , when we create a shopfy app with ruby template

    Description

    I created a Shopify app by Shopify ruby template with this command
    npm init @Shopify/app@latest -- --template=ruby

    I followed instruction of this Doc https://github.com/Shopify/shopify-app-template-ruby
    After setup when i run npm run dev to start server
    i got these logs

    15:16:32 │ web-frontend │ 
    15:16:32 │ web-frontend │ > [email protected] dev
    15:16:32 │ web-frontend │ > vite
    15:16:32 │ web-frontend │ 
    15:16:32 │ web-frontend │ 
    15:16:32 │ web-frontend │   VITE v4.5.0  ready in 332 ms
    15:16:32 │ web-frontend │ 
    15:16:32 │ web-frontend │   ➜  Local:   http://localhost:40627/
    15:16:32 │ webhooks     │ Sending APP_UNINSTALLED webhook to app server
    15:16:33 │ web-backend  │ => Booting Puma
    15:16:33 │ web-backend  │ => Rails 7.0.8 application starting in development 
    15:16:33 │ web-backend  │ => Run `bin/rails server --help` for more startup options
    15:16:33 │ web-backend  │ "Inside----------------------------------------- AppUniNstalled JOb"
    15:16:33 │ web-backend  │ Puma starting in single mode...
    15:16:33 │ web-backend  │ * Puma version: 5.6.7 (ruby 3.1.2-p20) ("Birdie's Version")
    15:16:33 │ web-backend  │ *  Min threads: 5
    15:16:33 │ web-backend  │ *  Max threads: 5
    15:16:33 │ web-backend  │ *  Environment: development
    15:16:33 │ web-backend  │ *          PID: 66023
    15:16:33 │ web-backend  │ * Listening on http://127.0.0.1:41021
    15:16:33 │ web-backend  │ * Listening on http://[::1]:41021
    15:16:33 │ web-backend  │ Use Ctrl-C to stop
    15:16:35 │ web-backend  │ Started POST "/api/webhooks" for 127.0.0.1 at 2023-12-01 15:16:35 +0530
    15:16:35 │ web-backend  │   ActiveRecord::SchemaMigration Pluck (0.1ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY 
    "schema_migrations"."version" ASC
    15:16:35 │ web-backend  │ "Insiede Application Controller"
    15:16:35 │ web-backend  │ Processing by HomeController#index as */*
    15:16:35 │ web-backend  │   Parameters: {"id"=>548380009, "name"=>"Super Toys", "email"=>"[email protected]", "domain"=>nil, 
    "province"=>"Tennessee", "country"=>"US", "address1"=>"190 MacLaren Street", "zip"=>"37178", "city"=>"Houston", "source"=>nil, 
    "phone"=>"3213213210", "latitude"=>nil, "longitude"=>nil, "primary_locale"=>"en", "address2"=>nil, "created_at"=>nil, "updated_at"=>nil, 
    "country_code"=>"US", "country_name"=>"United States", "currency"=>"USD", "customer_email"=>"[email protected]", "timezone"=>"(GMT-05:00) 
    Eastern Time (US & Canada)", "iana_timezone"=>nil, "shop_owner"=>"John Smith", "money_format"=>"${{amount}}", 
    "money_with_currency_format"=>"${{amount}} USD", "weight_unit"=>"kg", "province_code"=>"TN", "taxes_included"=>nil, 
    "auto_configure_tax_inclusivity"=>nil, "tax_shipping"=>nil, "county_taxes"=>nil, "plan_display_name"=>"Shopify Plus", "plan_name"=>"enterprise",
     "has_discounts"=>false, "has_gift_cards"=>true, "myshopify_domain"=>nil, "google_apps_domain"=>nil, "google_apps_login_enabled"=>nil, 
    "money_in_emails_format"=>"${{amount}}", "money_with_currency_in_emails_format"=>"${{amount}} USD", "eligible_for_payments"=>true, 
    "requires_extra_payments_agreement"=>false, "password_enabled"=>"[FILTERED]", "has_storefront"=>true, "finances"=>true, 
    "primary_location_id"=>655441491, "checkout_api_supported"=>true, "multi_location_enabled"=>true, "setup_required"=>false, 
    "pre_launch_enabled"=>false, "enabled_presentment_currencies"=>["USD"], "transactional_sms_disabled"=>false, 
    "marketing_sms_consent_enabled_at_checkout"=>false, "path"=>"api/webhooks", "home"=>{"id"=>548380009, "name"=>"Super Toys", 
    "email"=>"[email protected]", "domain"=>nil, "province"=>"Tennessee", "country"=>"US", "address1"=>"190 MacLaren Street", "zip"=>"37178", 
    "city"=>"Houston", "source"=>nil, "phone"=>"3213213210", "latitude"=>nil, "longitude"=>nil, "primary_locale"=>"en", "address2"=>nil, 
    "created_at"=>nil, "updated_at"=>nil, "country_code"=>"US", "country_name"=>"United States", "currency"=>"USD", 
    "customer_email"=>"[email protected]", "timezone"=>"(GMT-05:00) Eastern Time (US & Canada)", "iana_timezone"=>nil, "shop_owner"=>"John Smith",
     "money_format"=>"${{amount}}", "money_with_currency_format"=>"${{amount}} USD", "weight_unit"=>"kg", "province_code"=>"TN", 
    "taxes_included"=>nil, "auto_configure_tax_inclusivity"=>nil, "tax_shipping"=>nil, "county_taxes"=>nil, "plan_display_name"=>"Shopify Plus", 
    "plan_name"=>"enterprise", "has_discounts"=>false, "has_gift_cards"=>true, "myshopify_domain"=>nil, "google_apps_domain"=>nil, 
    "google_apps_login_enabled"=>nil, "money_in_emails_format"=>"${{amount}}", "money_with_currency_in_emails_format"=>"${{amount}} USD", 
    "eligible_for_payments"=>true, "requires_extra_payments_agreement"=>false, "password_enabled"=>"[FILTERED]", "has_storefront"=>true, 
    "finances"=>true, "primary_location_id"=>655441491, "checkout_api_supported"=>true, "multi_location_enabled"=>true, "setup_required"=>false, 
    "pre_launch_enabled"=>false, "enabled_presentment_currencies"=>["USD"], "transactional_sms_disabled"=>false, 
    "marketing_sms_consent_enabled_at_checkout"=>false}}
    15:16:35 │ web-backend  │ Can't verify CSRF token authenticity.
    15:16:35 │ web-backend  │ Completed 422 Unprocessable Entity in 0ms (ActiveRecord: 0.0ms | Allocations: 585)
    15:16:35 │ web-backend  │ 
    15:16:35 │ web-backend  │ 
    15:16:35 │ web-backend  │   
    15:16:35 │ web-backend  │ ActionController::InvalidAuthenticityToken (Can't verify CSRF token authenticity.):
    15:16:35 │ web-backend  │   
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/request_forgery_protection.rb:253:in `handle_unverified_request'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/request_forgery_protection.rb:286:in `handle_unverified_request'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/request_forgery_protection.rb:275:in `verify_authenticity_token'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:400:in `block in make_lambda'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:199:in `block (2 levels) in halting'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:200:in `block in halting'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:595:in `block in invoke_before'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:595:in `each'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:595:in `invoke_before'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:116:in `block in run_callbacks'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:138:in `run_callbacks'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/abstract_controller/callbacks.rb:233:in `process_action'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/rescue.rb:23:in `process_action'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/instrumentation.rb:67:in `block in process_action'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/notifications.rb:206:in `block in instrument'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/notifications.rb:206:in `instrument'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/instrumentation.rb:66:in `process_action'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
    15:16:35 │ web-backend  │ activerecord (7.0.8) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/abstract_controller/base.rb:151:in `process'
    15:16:35 │ web-backend  │ actionview (7.0.8) lib/action_view/rendering.rb:39:in `process'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal.rb:188:in `dispatch'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal.rb:251:in `dispatch'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/routing/route_set.rb:32:in `serve'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/journey/router.rb:50:in `block in serve'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/journey/router.rb:32:in `each'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/journey/router.rb:32:in `serve'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/routing/route_set.rb:852:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/tempfile_reaper.rb:15:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/etag.rb:27:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/conditional_get.rb:40:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/head.rb:12:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/http/content_security_policy.rb:36:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/session/abstract/id.rb:266:in `context'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/session/abstract/id.rb:260:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/cookies.rb:704:in `call'
    15:16:35 │ web-backend  │ activerecord (7.0.8) lib/active_record/migration.rb:638:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/callbacks.rb:99:in `run_callbacks'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/executor.rb:14:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/debug_exceptions.rb:28:in `call'
    15:16:35 │ web-backend  │ web-console (4.2.1) lib/web_console/middleware.rb:132:in `call_app'
    15:16:35 │ web-backend  │ web-console (4.2.1) lib/web_console/middleware.rb:28:in `block in call'
    15:16:35 │ web-backend  │ web-console (4.2.1) lib/web_console/middleware.rb:17:in `catch'
    15:16:35 │ web-backend  │ web-console (4.2.1) lib/web_console/middleware.rb:17:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/show_exceptions.rb:29:in `call'
    15:16:35 │ web-backend  │ railties (7.0.8) lib/rails/rack/logger.rb:40:in `call_app'
    15:16:35 │ web-backend  │ railties (7.0.8) lib/rails/rack/logger.rb:25:in `block in call'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/tagged_logging.rb:99:in `block in tagged'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/tagged_logging.rb:37:in `tagged'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/tagged_logging.rb:99:in `tagged'
    15:16:35 │ web-backend  │ railties (7.0.8) lib/rails/rack/logger.rb:25:in `call'
    15:16:35 │ web-backend  │ sprockets-rails (3.4.2) lib/sprockets/rails/quiet_assets.rb:13:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/remote_ip.rb:93:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/request_id.rb:26:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/method_override.rb:24:in `call'
    15:16:35 │ web-backend  │ shopify_app (21.7.0) lib/shopify_app/middleware/jwt_middleware.rb:24:in `call_next'
    15:16:35 │ web-backend  │ shopify_app (21.7.0) lib/shopify_app/middleware/jwt_middleware.rb:12:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/runtime.rb:22:in `call'
    15:16:35 │ web-backend  │ activesupport (7.0.8) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/server_timing.rb:61:in `block in call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/server_timing.rb:26:in `collect_events'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/server_timing.rb:60:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/executor.rb:14:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/static.rb:23:in `call'
    15:16:35 │ web-backend  │ rack (2.2.8) lib/rack/sendfile.rb:110:in `call'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_dispatch/middleware/host_authorization.rb:138:in `call'
    15:16:35 │ web-backend  │ railties (7.0.8) lib/rails/engine.rb:530:in `call'
    15:16:35 │ web-backend  │ puma (5.6.7) lib/puma/configuration.rb:252:in `call'
    15:16:35 │ web-backend  │ puma (5.6.7) lib/puma/request.rb:77:in `block in handle_request'
    15:16:35 │ web-backend  │ puma (5.6.7) lib/puma/thread_pool.rb:340:in `with_force_shutdown'
    15:16:35 │ web-backend  │ puma (5.6.7) lib/puma/request.rb:76:in `handle_request'
    15:16:35 │ web-backend  │ puma (5.6.7) lib/puma/server.rb:443:in `process_client'
    15:16:35 │ web-backend  │ puma (5.6.7) lib/puma/thread_pool.rb:147:in `block in spawn_thread'
    15:16:36 │ webhooks     │ APP_UNINSTALLED webhook delivery failed
    
    • shopify_api version: gem "shopify_api", "~> 13.3"
    • shopify_app version: gem "shopify_app", "~> 21.7"
    • Ruby version: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
    • Operating system: Ubuntu 20.04.6 LTS (64 bits)
    • Node version : v20.9.0
    • npm version : 10.2.4
    • rails version : Rails 7.0.8

    Expected behavior

    Webhook Should delivered Successfully and there will no issue of CSRF Authenticity

    Actual behavior

    15:16:35 │ web-backend  │ Can't verify CSRF token authenticity.
    15:16:35 │ web-backend  │ Completed 422 Unprocessable Entity in 0ms (ActiveRecord: 0.0ms | Allocations: 585)
    15:16:35 │ web-backend  │ 
    15:16:35 │ web-backend  │ 
    15:16:35 │ web-backend  │   
    15:16:35 │ web-backend  │ ActionController::InvalidAuthenticityToken (Can't verify CSRF token authenticity.):
    15:16:35 │ web-backend  │   
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/request_forgery_protection.rb:253:in `handle_unverified_request'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/request_forgery_protection.rb:286:in `handle_unverified_request'
    15:16:35 │ web-backend  │ actionpack (7.0.8) lib/action_controller/metal/request_forgery_protection.rb:275:in `verify_authenticity_token'
    

    WorkAround : bypassing csrf validation , delivered webhooks successfully

    # web/app/controllers/application_controller.rb
    class ApplicationController < ActionController::Base
      # it skips csrf token validation
      skip_forgery_protection
    end
    

    Steps to reproduce the problem

    Follow this guide and make a shopify app with rails template
    https://github.com/Shopify/shopify-app-template-ruby

    Tasks

    No tasks being tracked yet.

    Symlink Path Issues for assets: Absolute Path in Local Environment Breaks in Production on Linux

    Issue summary

    When deploying to a production environment (on fly.io with Linux), the application encounters a Errno::ENOENT error related to a symlink pointing to index.html in the public/dist directory. This symlink is generated correctly in a local Mac environment but fails in production due to its absolute path.

    • shopify_api version: 21.4
    • shopify_app version: 21.4
    • Ruby version: 3.1
    • Operating system: Mac for development, Linux on fly.io for production
    Errno::ENOENT
    No such file or directory @ rb_sysopen - /app/public/dist/index.html
    

    On a local Mac development machine:

    ➜  dist git:(main) ✗ ls -l
    total 0
    lrwxr-xr-x  1 yann  staff  98 Oct 12 15:03 index.html -> /Users/yann/Code/shopify/shopify_app/web/lib/tasks/../../frontend/dist/index.html
    

    Expected behavior

    The symlink for index.html should be relative and should resolve correctly regardless of the deployment environment, ensuring that the application can locate the index.html file.

    Actual behavior

    The symlink generated has an absolute path which works on the local Mac development environment but breaks when deployed to a production environment on fly.io with Linux.

    Steps to reproduce the problem

    1. Run the Rake task that generates the symlink in a local Mac environment : rake build:all
    2. Verify that the symlink is absolute and points to the correct index.html on the local machine.
    3. Deploy the application to a production environment on fly.io with Linux.
    4. Observe the Errno::ENOENT error when the application tries to access the index.html via the symlink.

    Rails 8, Hotwire, Stimulus, no react

    Hello Shopify!

    With the upcoming release of Rails 8, I think the default rails template for a Shopify app could deeply change. This is more a topic for discussions, but there is no discussions tab so here I am.

    In particular

    • Is React really needed? Embedded apps have a full page reload when changing from the app menu, and inside the app it could easily be another page (index.html.erb to show.html.erb), especially with Hotwire. A full stack dev could just get some Polaris designs and create a fully working app without needing to know one line of React
    • If needed, Stimulus could be used for interactivity, replacing the need for React
    • Kamal will sit on top of Docker / Kubernetes, allowing to deploy everywhere
    • solid queue and solid cache examples (especially on rate limiting Shopify's APIs) => rails/solid_queue#97

    Benefits

    • zero bundling and transpiling - way faster deployments (and easy to debug)
    • way faster development cycle
    • shorter learning curve
    • frontend developers focused on building extensions (admin, storefront, account, checkout etc)

    I am very interested in building something like this, I have already seen a few resources online (i.e. https://github.com/kirillplatonov/shopify-hotwire-sample) from @kirillplatonov.

    Is it interesting for Shopify as well? I'm asking because I can see an outdated Ruby version on this repo, for example, and official documentation mentioning only Remix templates.

    Implement rails system tests

    Issue summary

    Hi all! I'm trying to add system tests to my rails shopify app. It would be good to add them so we can make smoke test easily

    • shopify_api version: 12.2.1
    • shopify_app version: 3.21.0
    • shopify_cli: 3.21.0
    • Ruby version: 3.1.2
    • Rails version: 7.0.3
    • Operating system: macOS ventura

    Expected behavior

    I want to run a test ./bin/rails test test/system/my_first_test. I access the embedded app skipping/avoiding the shopify auth process. (The API calls that I call from the embedded app will return dummy data of course).
    Is there a way to do what I need?

    Instructions are wrong for using Cloudflare Tunnel instead of ngrok

    Issue summary

    The instructions to use Cloudflare Tunnel do not state the correct way to pass in an argument in yarn, npm or pnpm.

    Expected behavior

    The instructions should state that when setting up Cloudflare Tunnel, we pass in the tunnel-url argument like --tunnel-url=https://tunnel-url:3000. After running this command, we should see the below output.

    > [email protected] dev
    > shopify app dev
    
    ✔ Dependencies installed
    
    To run this command, log in to Shopify Partners.
    👉 Press any key to open the login page on your browser
    

    Actual behavior

    The instructions currently state that when setting up Cloudflare Tunnel, we pass in the tunnel-url argument like --tunnel-url https://tunnel-url:3000. After running this command, we see the below output.

    command app:dev:https://tunnel-url:3000 not found
    

    Steps to reproduce the problem

    1. Install the cloudflared CLI tool
    2. Run cloudflared tunnel --url http://localhost:3000 in a terminal window.
    3. In another terminal window run npm run dev --tunnel-url https://tunnel-url:3000.

    Reduced test case

    N/A

    Checklist

    • I have described this issue in a way that is actionable (if possible)

    `yarn dev` fails with "Warning: Invalid hook call." on new project

    Issue summary

    In a brand new project, yarn dev fails with

    Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
      See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
      Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
    4. You might have mismatching versions of React and the renderer (such as React DOM)
    5. You might be breaking the Rules of Hooks
    6. You might have more than one copy of React in the same app
      See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

    ERROR Cannot read properties of null (reading 'useContext')

    • shopify_api version: 13.4.0
    • shopify_app version: 21.10.0
    • Ruby version: 3.2.2
    • Operating system: macOS Ventura 13.6.4
    > yarn dev        
    yarn run v1.22.21
    $ shopify app dev
    ╭─ info ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
    │                                                                                                                               │
    │  Using shopify.app.toml:                                                                                                      │
    │                                                                                                                               │
    │    • Org:             Ada Apps                                                                                                │
    │    • App:             2024-01-29-ruby-template                                                                                │
    │    • Dev store:       2024-01-29-ruby-template.myshopify.com                                                                  │
    │    • Update URLs:     Yes                                                                                                     │
    │                                                                                                                               │
    │   You can pass `--reset` to your command to reset your app configuration.                                                     │
    │                                                                                                                               │
    ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
    
    Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    
      ERROR  Cannot read properties of null (reading 'useContext')
    
     node_modules/@shopify/app/node_modules/react/cjs/react.development.js:1618:21
    
     1615:     }
     1616:   }
     1617:
     1618:   return dispatcher.useContext(Context);
     1619: }
     1620: function useState(initialState) {
     1621:   var dispatcher = resolveDispatcher();
    
     - useContext (node_modules/@shopify/app/node_modules/react/cjs/react.development.js:1618:21)
     - useStdin (node_modules/@shopify/app/node_modules/ink/build/hooks/use-stdin.js:6:24)
     - Dev (node_modules/@shopify/app/dist/cli/services/dev/ui/components/Dev.js:13:53)
     - renderWithHooks (node_modules/@shopify/cli-kit/node_modules/react-reconciler/cjs/react-reconciler.development.js:7478:18)
     - mountIndeterminateComponent (node_modules/@shopify/cli-kit/node_modules/react-reconciler/cjs/react-reconciler.development.js:11247:13)
     - beginWork (node_modules/@shopify/cli-kit/node_modules/react-reconciler/cjs/react-reconciler.development.js:12760:16)
     - beginWork$1 (node_modules/@shopify/cli-kit/node_modules/react-reconciler/cjs/react-reconciler.development.js:19569:14)
     - performUnitOfWork (node_modules/@shopify/cli-kit/node_modules/react-reconciler/cjs/react-reconciler.development.js:18703:12)
     - workLoopSync (node_modules/@shopify/cli-kit/node_modules/react-reconciler/cjs/react-reconciler.development.js:18609:5)
     - renderRootSync (node_modules/@shopify/cli-kit/node_modules/react-reconciler/cjs/react-reconciler.development.js:18577:7)
    

    Expected behavior

    The app starts without any errors.

    Actual behavior

    There's a React error with little information

    Steps to reproduce the problem

    1. yarn create @shopify/app --template=ruby
    2. cd <proj_name>
    3. yarn dev

    Typescript Support

    Issue summary

    • shopify_api version:
    • shopify_app version:
    • Ruby version:
    • Operating system:
    // Paste any relevant logs here
    

    Expected behavior

    Actual behavior

    Steps to reproduce the problem

    Expected a JavaScript module script but the server responded with a MIME type of "text/html"

    Issue summary

    When front end getting load with console error and log error and component not rendering

    • shopify_api version: 2023-10

    • shopify_app version: 21.4

    • Ruby version: 3.2.2

    • Rails version: 7.0.3

    • Operating system: linux

    • Logs:-

    17:37:52 │ web-backend  │ Started GET "/index.jsx" for 2401:4900:1c80:84e4:7c05:37fb:8ecb:bbf4 at 2023-10-19 17:37:52 +0530
    17:37:52 │ web-backend  │ Cannot render console from 2401:4900:1c80:84e4:7c05:37fb:8ecb:bbf4! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    17:37:52 │ web-backend  │ Processing by HomeController#index as */*
    17:37:52 │ web-backend  │   Parameters: {"path"=>"index"}
    17:37:52 │ web-backend  │ Redirected to https://sought-generous-reptile.ngrok-free.app/api/auth
    17:37:52 │ web-backend  │ Filter chain halted as :check_shop_domain rendered or redirected
    17:37:52 │ web-backend  │ Completed 302 Found in 2ms (ActiveRecord: 0.0ms | Allocations: 154)
    17:37:52 │ web-backend  │ 
    17:37:52 │ web-backend  │ 
    17:37:52 │ web-backend  │ Started GET "/dev_embed.js" for 2401:4900:1c80:84e4:7c05:37fb:8ecb:bbf4 at 2023-10-19 17:37:52 +0530
    17:37:52 │ web-backend  │ Cannot render console from 2401:4900:1c80:84e4:7c05:37fb:8ecb:bbf4! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    17:37:52 │ web-backend  │ Processing by HomeController#index as JS
    17:37:52 │ web-backend  │   Parameters: {"path"=>"dev_embed"}
    17:37:52 │ web-backend  │ Redirected to https://sought-generous-reptile.ngrok-free.app/api/auth
    17:37:52 │ web-backend  │ Filter chain halted as :check_shop_domain rendered or redirected
    17:37:52 │ web-backend  │ Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 154)
    17:37:52 │ web-backend  │ 
    17:37:52 │ web-backend  │ 
    17:37:52 │ web-backend  │ Started GET "/api/auth" for 2401:4900:1c80:84e4:7c05:37fb:8ecb:bbf4 at 2023-10-19 17:37:52 +0530
    17:37:52 │ web-backend  │ Cannot render console from 2401:4900:1c80:84e4:7c05:37fb:8ecb:bbf4! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    17:37:52 │ web-backend  │ Processing by ShopifyApp::SessionsController#new as */*
    17:37:52 │ web-backend  │   Rendering /home/dell1/.rvm/gems/ruby-3.1.2/gems/shopify_app-21.7.0/app/views/shopify_app/sessions/new.html.erb
    17:37:52 │ web-backend  │   Rendered /home/dell1/.rvm/gems/ruby-3.1.2/gems/shopify_app-21.7.0/app/views/shopify_app/partials/_layout_styles.html.erb (Duration: 0.0ms | Allocations: 9)
    17:37:52 │ web-backend  │   Rendered /home/dell1/.rvm/gems/ruby-3.1.2/gems/shopify_app-21.7.0/app/views/shopify_app/partials/_typography_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    17:37:52 │ web-backend  │   Rendered /home/dell1/.rvm/gems/ruby-3.1.2/gems/shopify_app-21.7.0/app/views/shopify_app/partials/_card_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    17:37:52 │ web-backend  │   Rendered /home/dell1/.rvm/gems/ruby-3.1.2/gems/shopify_app-21.7.0/app/views/shopify_app/partials/_button_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    17:37:52 │ web-backend  │   Rendered /home/dell1/.rvm/gems/ruby-3.1.2/gems/shopify_app-21.7.0/app/views/shopify_app/partials/_form_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    17:37:52 │ web-backend  │   Rendered /home/dell1/.rvm/gems/ruby-3.1.2/gems/shopify_app-21.7.0/app/views/shopify_app/sessions/new.html.erb (Duration: 1.6ms | Allocations: 567)
    17:37:52 │ web-backend  │ Completed 200 OK in 2ms (Views: 2.0ms | ActiveRecord: 0.0ms | Allocations: 805)
    
    • Console error

    Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

    rake build:all fails with error in root directory of app

    Issue summary

    rake aborted!
    Errno::ENOENT: No such file or directory @ rb_file_s_symlink - (/home/devender/appwoods-app/appwood-faq-plus/web/lib/tasks/../../frontend/dist/index.html, /home/devender/appwoods-app/appwood-faq-plus/web/lib/tasks/../../public/dist/index.html)
    /home/devender/appwoods-app/appwood-faq-plus/web/lib/tasks/build.rake:12:in symlink' /home/devender/appwoods-app/appwood-faq-plus/web/lib/tasks/build.rake:12:in block (2 levels) in

    '
    Tasks: TOP => build:all => build:build_frontend_links
    (See full trace by running task with --trace)

    Steps to reproduce the problem

    cd web/frontend
    SHOPIFY_API_KEY=REPLACE_ME npm run build
    cd ..
    rake build:all

    #48 (comment)

    How can I add new environment variable for FrontEnd con local?

    # heroku.yml
    build:
      docker:
        web: Dockerfile.web
        worker: Dockerfile.worker
      config:
        SHOPIFY_API_KEY: API_KEY
        KEY: VALUE
    # frontend/vite.config.js
    // rest of the code
    
    export default defineConfig({
      root: dirname(fileURLToPath(import.meta.url)),
      plugins: [react()],
      define: {
        "process.env.SHOPIFY_API_KEY": JSON.stringify(process.env.SHOPIFY_API_KEY),
        "process.env.KEY": JSON.stringify(process.env.KEY),
      },
     // rest config
    });

    This works on production. But how can I add KEY env on local?

    Incorrect npm run Command in README.md Causes Build Failures

    Issue summary

    When attempting to follow the build instructions in the README.md for the shopify repository, I noticed that the npm run command for passing arguments was incorrect. Specifically, it lacked the -- required before passing any arguments to the script, causing confusion and unsuccessful builds (no api key).

    Expected behavior

    The README.md should guide users to use the correct command:

    npm run build -- --api-key=REPLACE_ME

    Actual behavior

    The current README.md instructs users to use the incorrect command:

    npm run build --api-key=REPLACE_ME

    This does not correctly pass the api-key argument to the script, leading to build failures.

    Steps to reproduce the problem

    run the command and see the error due to missing api-key

    npm run build --api-key=REPLACE_ME

    The issue is fixed in #106

    Stuck in /api/auth -> /api/auth/callback loop w/ default template

    Issue summary

    I'm using a fresh install of the shopify-app-template-ruby template. everything works great locally, but when I deploy to Heroku using the Docker container, and try to install the app, I get stuck in a 302 loop between /api/auth <-> /api/auth/callback before getting the dreaded:

    The app couldn’t be loaded This app can’t load due to an issue with browser cookies. Try enabling cookies in your browser, [switching to another browser](https://community.shopify.com/c/Shopify-Apps/Some-Third-Party-Apps-may-not-be-accessible-on-Chrome-80-update/m-p/650220/thread-id/20503), or contacting the developer to get support.

    I've actually tried this with two completely different apps and Heroku deployments and get the same result.

    Expected behavior

    The app should load when selected.

    Actual behavior

    Browser & app redirect back and forth at several times before erroring out.

    Steps to reproduce the problem

    1. Start a new app using the template generator
    2. Setup & deploy to Heroku, using container instructions.

    Error while running an app

    when i make a new app using this template app (i.e. https://github.com/Shopify/shopify-app-template-ruby) is not running and get the following error

    npm init @shopify/app@latest -- --template=ruby
    cd web
    bundle install
    bin/rails app:template LOCATION=./template.rb
    cd ..
    npm run dev

    all is working fine but when i run npm run dev i get the following error
    Error:
    ── external error ──────────────────────────────

    Error coming from bin/rails server

    Command failed with exit code 1: bin/rails
    server
    C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:332:in raise_not_found!': Could not find gem 'shopify_app (~> 21.9)' in locally installed gems. (Bundler::GemNotFound) from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:392:in block in
    prepare_dependencies'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:377:in each' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:377:in map'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:377:in
    prepare_dependencies' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:61:in setup_solver' from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:28:in start' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:626:in start_resolution'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:311:in resolve' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:579:in materialize'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:203:in specs' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:270:in specs_for' from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/runtime.rb:18:in setup' from C:/Users/Buzz Tech/.local/share/gem/ruby/3. 2.0/gems/bundler-2.5.6/lib/bundler.rb:162:in setup'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/setup.rb:26:in block in <top (required)>' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/ui/shell.rb:159:in with_level'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/ui/shell.rb:111:in silence' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/setup.rb:26:in <top
    (required)>'
    from <internal:C:/Ruby32-x64/lib/ruby/3.2.0/ruby
    gems/core_ext/kernel_require.rb>:85:in require' from <internal:C:/Ruby32-x64/lib/ruby/3.2.0/ruby gems/core_ext/kernel_require.rb>:85:in require' from C:/Users/Buzz Tech/Desktop/New folder/conso
    lidated-trade-app/web/config/boot.rb:6:in <top (required)>' from C:/Users/Buzz Tech/Desktop/New folder/consolidated-trade-app/web/bin/rails:3:in require_relative'
    from C:/Users/Buzz Tech/Desktop/New
    folder/consolidated-trade-app/web/bin/rails:3:in `

    '

    Screenshot 2024-02-19 010600

    Screenshot 2024-02-19 010641

    Screenshot 2024-02-19 010705
    Screenshot 2024-02-19 010732

    • shopify_api version:
    • shopify_app version: 3.56.1
    • Ruby version: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mingw-ucrt]
    • Operating system: wundows

    when i run npm run dev after creating an app get the following error istead of running an app
    ── external error ──────────────────────────────

    Error coming from bin/rails server

    Command failed with exit code 1: bin/rails
    server
    C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:332:in raise_not_found!': Could not find gem 'shopify_app (~> 21.9)' in locally installed gems. (Bundler::GemNotFound) from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:392:in block in
    prepare_dependencies'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:377:in each' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:377:in map'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:377:in
    prepare_dependencies' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:61:in setup_solver' from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/resolver.rb:28:in start' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:626:in start_resolution'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:311:in resolve' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:579:in materialize'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:203:in specs' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/definition.rb:270:in specs_for' from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/runtime.rb:18:in setup' from C:/Users/Buzz Tech/.local/share/gem/ruby/3. 2.0/gems/bundler-2.5.6/lib/bundler.rb:162:in setup'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/setup.rb:26:in block in <top (required)>' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/ui/shell.rb:159:in with_level'
    from C:/Users/Buzz
    Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/ui/shell.rb:111:in silence' from C:/Users/Buzz Tech/.local/share/gem/ruby/3.2.0/gems/bundler-2.5.6/lib/bundler/setup.rb:26:in <top
    (required)>'
    from <internal:C:/Ruby32-x64/lib/ruby/3.2.0/ruby
    gems/core_ext/kernel_require.rb>:85:in require' from <internal:C:/Ruby32-x64/lib/ruby/3.2.0/ruby gems/core_ext/kernel_require.rb>:85:in require' from C:/Users/Buzz Tech/Desktop/New folder/conso
    lidated-trade-app/web/config/boot.rb:6:in <top (required)>' from C:/Users/Buzz Tech/Desktop/New folder/consolidated-trade-app/web/bin/rails:3:in require_relative'
    from C:/Users/Buzz Tech/Desktop/New
    folder/consolidated-trade-app/web/bin/rails:3:in `

    '

    Default template breaks. Missing keyword: :session_storage

    Issue summary

    Template breaks on initialization, I seem to get this error

    /.../shopify_api-12.2.1/lib/shopify_api/context.rb:44:in `setup': missing  keyword: :session_storage (ArgumentError)
    

    It seems if I revert the changes in this commit. I can get everything working again

    Maybe I'm being silly and its an issue with versions?

    UI not rendering in production

    I've been trying to deploy the default shopify rails+react app generated via shopify cli

    Deployment is successful but the UI doesn't get rendered. I get a blank screen with the message "This app does not appear to be loading and may be outdated. Try reloading the app in the legacy admin or contact the app's developer to update the app." The same issue persists when I load the app in legacy admin as well.

    image

    For now, I've tried the following:

    1. Running the Dockerfile locally
    2. Run all commands from Dockerfile locally - bundle install, npm install, npm run build, rake build:all and rails server -b 0.0.0.0 -e production
    3. Deploy the app to production on cloud66 (which runs the default Dockerfile)

    All 3 have the same issue. Don't see any errors in Rails logs as well.

    Can anyone help please?

    Shopify CLI v3.39.0
    Rails v7.0.3
    Node version v19.1.0
    Shopify App Gem v21.4

    `yarn create @shopify/app --template=ruby` failed

    Issue summary

    yarn create @shopify/app --template=ruby failed

    • Operating system:
      • yarn: 1.22.19
      • node: 16.17.1
    Show error
    yarn create @shopify/app --template=ruby
    yarn create v1.22.19
    [1/4] 🔍  Resolving packages...
    [2/4] 🚚  Fetching packages...
    [3/4] 🔗  Linking dependencies...
    [4/4] 🔨  Building fresh packages...
    success Installed "@shopify/[email protected]" with binaries:
          - create-app
    
    Welcome. Let’s get started by naming your app. You can change it later.
    ✔ Your app's name? · pc-ordes
    ✔ Downloaded template from https://github.com/Shopify/shopify-app-template-ruby
     384,
          download: undefined,
          total: 5086
          }
          }
          }
          ngrok - install failed, retrying
          ngrok - downloading binary https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-darwin-amd64.zip
    ngrok - downloading progress: 2372/88
    ngrok -
    ngrok - downloading progr
    ngrok - downloading progress: 34177/8885946
    ngrok - do
    ngrok - downloading progress
    ngrok - downloading progress: 80513/8885946 (0
    ngrok - down
    ngrok - downloading progress
    ngrok - downloading progress: 199089/8885946
    ngrok -
    ngrok - downloading prog
    ngrok - downloading progress: 313777/888
    ngrok
    ngrok - downloading p
    ngrok - downloading progress: 428465/
    ngrok
    ngrok - downloading p
    ngrok - downloading progress: 543153/
    ngrok
    ngrok - downloading p
    ngrok - downloading progress: 657841/
    ngrok
    ngrok - downloading p
    ngrok - downloading progress: 772529/
    ngrok
    ngrok - downloading p
    ngrok - downloading progress: 887217/
    ngrok - downloading progress: 919985/8885946 (10.35%
    ngrok - downl
    ngrok - downloading progres
    ngrok - downloading progress: 1034673/8
    ngrok - downloading progress: 1067441/8885946 (12.0
    ngrok - d
    ngrok - downloading p
    ngrok - downloading progress: 118
    ngrok - downloading progress: 1214897/8885946
    ngrok
    ngrok - downloadi
    ngrok - downloading progress:
    ngrok - downloading progress: 1362353/888
    ngrok - downloading progress: 1395121/8885946 (15.70%
    ✔ App initialized
      ✔ Liquid parsed
      ✔ Updated package.json
    ❯ Installing dependencies with yarn
      ⠋ Installing dependencies in /
    ngrok - downloading p
    ngrok - downloading progress: 185
    ngrok - downloading progress: 1886641/8885946
    ngrok
    ngrok - downloadi
    ngrok - downloading progress:
    ngrok - downloading progress: 2034097/888
    ngrok - downloading progress: 2066865/8885946 (23.26%
    ngrok - dow
    ngrok - downloading pro
    ngrok - downloading progress: 21815
    ngrok - downloading progress: 2214321/8885946 (
    ngrok
    ngrok - downloadi
    ngrok - downloading progress:
    ngrok - downloading progress: 2361777/888
    ngrok - downloading progress: 2394545/8885946 (26.95%
    ngrok - dow
    ngrok - downloading pro
    ngrok - downloading progress: 25092
    ngrok - downloading progress: 2542001/8885946 (
    ngrok
    ngrok - downloadi
    ngrok - downloading progress:
    ngrok - downloading progress: 2689457/888
    ngrok - downloading progress: 2722225/8885946 (30.64%
    ngrok - dow
    ngrok - downloading pro
    ngrok - downloading progress: 28369
    ngrok - downloading progress: 2869681/8885946 (
    ngrok
    ngrok - downloadi
    ngrok - downloading progress:
    ngrok - downloading progress: 3017137/888
    ngrok - downloading progress: 3049905/8885946 (34.32%
    ngrok - dow
    ngrok - downloading pro
    ngrok - downloading progress: 31645
    ngrok - downloading progress: 3197361/8885946 (
    ngrok
    ngrok - downloadi
    ngrok - downloading progress:
    ngrok - downloading progress: 3344817/888
    ngrok - downloading progress: 3377585/8885946 (38.01%
    ngrok - dow
    ngrok - downloading pro
    ngrok - downloading progress: 34922
    ngrok - downloading progress: 3525041/8885946 (
    ngrok
    ngrok - downloadi
    ✔ App initialized
      ✔ Liquid parsed
      ✔ Updated package.json
    ❯ Installing dependencies with yarn
      ✖ Command failed with exit code 1: yarn install
    warning "@shopify/app > @luckycatfactory/[email protected]" has unmet peer dependency "graphql-tag@^2.…
    warning "@shopify/app > @shopify/shopify-cli-extensions > @luckycatfactory/[email protected]" has unme…
    warning "@shopify/app > @shopify/shopify-cli-extensions > @luckycatfactory/[email protected]" has unme…
    error /private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805b3129/app/node_modules/…
        Exit code: 1
        Command: node ./postinstall.js
        Arguments:
        Directory: /private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805b3129/app/node_mod…
        Output:
        ngrok - downloading binary https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-darwin-amd64.zip
    ngrok - downloading progress: 432809/8885946 (4.87%)…
        ngrok - error downloading from URL ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
        code: 'ECONNRESET',
        timings: {
        start: 1673430500673,
        socket: 1673430500675,
        lookup: 1673430502217,
        connect: 1673430502498,
        secureConnect: 1673430502841,
        upload: 1673430502842,
        response: 1673430503166,
        end: undefined,
        error: 1673430505532,
        abort: 1673430505533,
        phases: {
        wait: 2,
        dns: 1542,
        tcp: 281,
        tls: 343,
        request: 1,
        firstByte: 324,
        download: undefined,
        total: 4860
        }
        }
        }
        ngrok - install failed, retrying
        ngrok - downloading binary https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-darwin-amd64.zip
    ngrok - downloading progress: 669881/8885946 (7.54%)…
        ngrok - error downloading from URL ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
        code: 'ECONNRESET',
        timings: {
        start: 1673430506038,
        socket: 1673430506039,
        lookup: 1673430506301,
        connect: 1673430506567,
        secureConnect: 1673430506906,
        upload: 1673430506906,
        response: 1673430507290,
        end: undefined,
        error: 1673430511123,
        abort: 1673430511124,
        phases: {
        wait: 1,
        dns: 262,
        tcp: 266,
        tls: 339,
        request: 0,
        firstByte: 384,
        download: undefined,
        total: 5086
        }
        }
        }
        ngrok - install failed, retrying
        ngrok - downloading binary https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-darwin-amd64.zip
    ngrok - downloading progress: 3901873/8885946 (43.91%)…
        ngrok - error downloading from URL ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
        code: 'ECONNRESET',
        timings: {
        start: 1673430511627,
        socket: 1673430511628,
        lookup: 1673430511629,
        connect: 1673430511896,
        secureConnect: 1673430512236,
        upload: 1673430512236,
        response: 1673430512586,
        end: undefined,
        error: 1673430521401,
        abort: 1673430521401,
        phases: {
        wait: 1,
        dns: 1,
        tcp: 267,
        tls: 340,
        request: 0,
        firstByte: 350,
        download: undefined,
        total: 9774
        }
        }
        }
        ngrok - install failed ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3…
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
        code: 'ECONNRESET',
        timings: {
        start: 1673430511627,
        socket: 1673430511628,
        lookup: 1673430511629,
        connect: 1673430511896,
        secureConnect: 1673430512236,
        upload: 1673430512236,
        response: 1673430512586,
        end: undefined,
        error: 1673430521401,
        abort: 1673430521401,
        phases: {
        wait: 1,
        dns: 1,
        tcp: 267,
        tls: 340,
        request: 0,
        firstByte: 350,
        download: undefined,
        total: 9774
        }
        }
        }
    yarn install v1.22.19
    info No lockfile found.
    [1/4] Resolving packages...
    [2/4] Fetching packages...
    [3/4] Linking dependencies...
    [4/4] Building fresh packages...
    info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
      ◼ Installing dependencies in /web/frontend/
    ◼ Clean up
    ◼ Initializing a Git repository...
    
    ── external error ──────────────────────────────────────────────────────────────
    
    Error coming from `yarn install`
    
    Command failed with exit code 1: yarn install
    warning "@shopify/app > @luckycatfactory/[email protected]" has unmet peer dependency "graphql-tag@^2.11.0".
    warning "@shopify/app > @shopify/shopify-cli-extensions > @luckycatfactory/[email protected]" has unmet peer
    dependency "graphql-tag@^2.11.0".
    warning "@shopify/app > @shopify/shopify-cli-extensions > @luckycatfactory/[email protected]" has unmet peer
    dependency "graphql@^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0".
    error /private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805b3129/app/node_modules/@shopif
    y/ngrok: Command failed.
    Exit code: 1
    Command: node ./postinstall.js
    Arguments:
    Directory: /private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805b3129/app/node_modules/@s
    hopify/ngrok
    Output:
    ngrok - downloading binary https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-darwin-amd64.zip
    ngrok - downloading progress: 2372/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 48657/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 92097/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 219817/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 367273/8885946
    ngrok -
    ngrok - downloading progress: 432809/8885946 (4.87%)
    ngrok - error downloading from URL ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/got/dist/source/core/index.js:809:31)
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/@szmarczak/http-timer/dist/source/index.js:43:20)
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
      code: 'ECONNRESET',
      timings: {
        start: 1673430500673,
        socket: 1673430500675,
        lookup: 1673430502217,
        connect: 1673430502498,
        secureConnect: 1673430502841,
        upload: 1673430502842,
        response: 1673430503166,
        end: undefined,
        error: 1673430505532,
        abort: 1673430505533,
        phases: {
          wait: 2,
          dns: 1542,
          tcp: 281,
          tls: 343,
          request: 1,
          firstByte: 324,
          download: undefined,
          total: 4860
        }
      }
    }
    ngrok - install failed, retrying
    ngrok - downloading binary https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-darwin-amd64.zip
    ngrok - downloading progress: 2372/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 48657/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 129209/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 276665/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 424121/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 571577/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress: 669881/8885946 (7.54%)
    ngrok - error downloading from URL ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/got/dist/source/core/index.js:809:31)
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/@szmarczak/http-timer/dist/source/index.js:43:20)
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
      code: 'ECONNRESET',
      timings: {
        start: 1673430506038,
        socket: 1673430506039,
        lookup: 1673430506301,
        connect: 1673430506567,
        secureConnect: 1673430506906,
        upload: 1673430506906,
        response: 1673430507290,
        end: undefined,
        error: 1673430511123,
        abort: 1673430511124,
        phases: {
          wait: 1,
          dns: 262,
          tcp: 266,
          tls: 339,
          request: 0,
          firstByte: 384,
          download: undefined,
          total: 5086
        }
      }
    }
    ngrok - install failed, retrying
    ngrok - downloading binary https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-darwin-amd64.zip
    ngrok - downloading progress: 2372/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 47209/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 149937/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 297393/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 444849/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 592305/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 739761/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress: 887217/8885946
    ngrok -
    ngrok - downloading
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress:
    ngrok - downloading progress: 3901873/8885946 (43.91%)
    ngrok - error downloading from URL ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/got/dist/source/core/index.js:809:31)
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/@szmarczak/http-timer/dist/source/index.js:43:20)
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
      code: 'ECONNRESET',
      timings: {
        start: 1673430511627,
        socket: 1673430511628,
        lookup: 1673430511629,
        connect: 1673430511896,
        secureConnect: 1673430512236,
        upload: 1673430512236,
        response: 1673430512586,
        end: undefined,
        error: 1673430521401,
        abort: 1673430521401,
        phases: {
          wait: 1,
          dns: 1,
          tcp: 267,
          tls: 340,
          request: 0,
          firstByte: 350,
          download: undefined,
          total: 9774
        }
      }
    }
    ngrok - install failed ReadError: The server aborted pending request
        at IncomingMessage.<anonymous> (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/got/dist/source/core/index.js:809:31)
        at Object.onceWrapper (node:events:627:28)
        at IncomingMessage.emit (node:events:525:35)
        at IncomingMessage.origin.emit (/private/var/folders/mp/gx458m3x0c5__tsxrgcczs880000gn/T/12a1ead2fcb85f245b816ea3805
    b3129/app/node_modules/@szmarczak/http-timer/dist/source/index.js:43:20)
        at IncomingMessage._destroy (node:_http_incoming:224:10)
        at _destroy (node:internal/streams/destroy:102:25)
        at IncomingMessage.destroy (node:internal/streams/destroy:64:5)
        at TLSSocket.socketCloseListener (node:_http_client:441:11)
        at TLSSocket.emit (node:events:525:35)
        at node:net:757:14 {
      code: 'ECONNRESET',
      timings: {
        start: 1673430511627,
        socket: 1673430511628,
        lookup: 1673430511629,
        connect: 1673430511896,
        secureConnect: 1673430512236,
        upload: 1673430512236,
        response: 1673430512586,
        end: undefined,
        error: 1673430521401,
        abort: 1673430521401,
        phases: {
          wait: 1,
          dns: 1,
          tcp: 267,
          tls: 340,
          request: 0,
          firstByte: 350,
          download: undefined,
          total: 9774
        }
      }
    }
    yarn install v1.22.19
    info No lockfile found.
    [1/4] Resolving packages...
    [2/4] Fetching packages...
    [3/4] Linking dependencies...
    [4/4] Building fresh packages...
    info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
    
    ────────────────────────────────────────────────────────────────────────────────
    
    error Command failed.
    Exit code: 1
    Command: /usr/local/bin/create-app
    Arguments: --template=ruby
    Directory: /Users/admin/Other/shopify
    Output:
    
    info Visit https://yarnpkg.com/en/docs/cli/create for documentation about this command.
    

    Expected behavior

    Creates shopify_app template successfully.

    Actual behavior

    It is failed to create template.

    Steps to reproduce the problem

    yarn create @shopify/app --template=ruby

    Update DockerFile and Add docker-compose.yml file in Template

    Issue summary

    I want to request you to Update DockerFile in Such a way the user can change its database to postgres , Mysql, Mongodb easily
    Also Please add some more configuration regrading Sidekiq, Redis

    Please Provide us a docker-compose.yml file with configuration for postgres, mysql , redis, mongodb, and Sidekiq
    it will helps us to quick build and deployment

    Template is spawning problems

    If the CLI 3 is used to spawn a new Ruby App in Shopify using this template, the new App triggers warnings to the merchant that the App is not ready for admin.shopify.com and will open in a new tab. Also, the template is hard-coded to deliver App Bridge 2 whereas modern Shopify Apps are App Bridge 3.

      <script src="https://unpkg.com/@shopify/app-bridge@2"></script>
    
    • shopify_api version: 12.4
    • shopify_app version: 21.4
    • Ruby version: 3.2
    • Operating system: MacOS

    Feat: Server-side rendering

    This is a feature request, not an issue.

    I don't know how it would be possible with the frontend and backend being different apps, but I would still like to have it happen. If anyone knows how it could be accomplished I might even take a crack at it.

    Docker Error: Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

    image (4)
    image (5)
    image (6)
    image (7)

    Issue summary

    I created a app use shopify ruby template , I used the default Dockerfile give by ruby template
    I created a build , but my app is not working

    # Dockerfile
    FROM ruby:3.1-alpine
    
    ARG SHOPIFY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxx
    ENV SHOPIFY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
    RUN apk add libpq-dev
    RUN apk update && apk add nodejs npm git build-base postgresql-client  gcompat bash openssl-dev
    WORKDIR /app
    
    COPY web .
    
    RUN cd frontend && npm install
    RUN bundle install
    
    RUN cd frontend && npm run build
    RUN rake build:all
    
    COPY entrypoint.sh /usr/bin/
    RUN chmod +x /usr/bin/entrypoint.sh
    
    ENTRYPOINT ["entrypoint.sh"]
    
    CMD rails server -b 0.0.0.0
    
    # docker-compose.yml
    version: '3'
    services:
      db:
        image: postgres
        volumes:
          - ./web/tmp/db:/var/lib/postgresql/data
        environment:
          POSTGRES_USER: postgres    
          POSTGRES_PASSWORD: postgres
      app:
        build: .
        image: rails-web
        environment:
          SHOPIFY_API_KEY: xxxxxxxxxxxxxxxxxxxxxxxxx
          SHOPIFY_API_SECRET: xxxxxxxxxxxxxxxxxxxxxxxxxxx
          HOST: https://e70f-xxx-xxxx-553-634f-6a31-11e8-2e5d.ngrok-free.app
        stdin_open: true
        tty: true
        ports:
          - "80:3000"
        working_dir: /web
        volumes:
          - ./web:/web
        depends_on:
          - db
    

    These are my dockerfile and docker-compose.yml file

    Creating remix-shopify-rails_db_1 ... done
    Creating remix-shopify-rails_app_1 ... done
    Attaching to remix-shopify-rails_db_1, remix-shopify-rails_app_1
    db_1   | 
    db_1   | PostgreSQL Database directory appears to contain a database; Skipping initialization
    db_1   | 
    db_1   | 2023-12-19 06:53:47.311 UTC [1] LOG:  starting PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
    db_1   | 2023-12-19 06:53:47.311 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
    db_1   | 2023-12-19 06:53:47.311 UTC [1] LOG:  listening on IPv6 address "::", port 5432
    db_1   | 2023-12-19 06:53:47.394 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
    db_1   | 2023-12-19 06:53:47.476 UTC [30] LOG:  database system was shut down at 2023-12-19 06:46:08 UTC
    db_1   | 2023-12-19 06:53:47.502 UTC [1] LOG:  database system is ready to accept connections
    db_1   | 2023-12-19 06:53:52.020 UTC [34] ERROR:  database "remix_docker_development" already exists
    db_1   | 2023-12-19 06:53:52.020 UTC [34] STATEMENT:  CREATE DATABASE "remix_docker_development" ENCODING = 'unicode'
    app_1  | Database 'remix_docker_development' already exists
    db_1   | 2023-12-19 06:53:52.038 UTC [35] ERROR:  database "remix_docker_test" already exists
    db_1   | 2023-12-19 06:53:52.038 UTC [35] STATEMENT:  CREATE DATABASE "remix_docker_test" ENCODING = 'unicode'
    app_1  | Database 'remix_docker_test' already exists
    app_1  | => Booting Puma
    app_1  | => Rails 7.0.8 application starting in development 
    app_1  | => Run `bin/rails server --help` for more startup options
    app_1  | Puma starting in single mode...
    app_1  | * Puma version: 5.6.7 (ruby 3.1.4-p223) ("Birdie's Version")
    app_1  | *  Min threads: 5
    app_1  | *  Max threads: 5
    app_1  | *  Environment: development
    app_1  | *          PID: 1
    app_1  | * Listening on http://0.0.0.0:3000
    app_1  | Use Ctrl-C to stop
    app_1  | Started GET "/" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:53:58 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  |   ActiveRecord::SchemaMigration Pluck (0.5ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
    app_1  | Processing by HomeController#index as HTML
    app_1  | Redirected to https://e70f-2402-e280-230d-553-634f-6a31-11e8-2e5d.ngrok-free.app/api/auth
    app_1  | Filter chain halted as :check_shop_domain rendered or redirected
    app_1  | Completed 302 Found in 4ms (ActiveRecord: 0.0ms | Allocations: 1977)
    app_1  | 
    app_1  | 
    app_1  | Started GET "/api/auth" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:53:58 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  | Processing by ShopifyApp::SessionsController#new as HTML
    app_1  |   Rendering /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/sessions/new.html.erb
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_layout_styles.html.erb (Duration: 0.3ms | Allocations: 293)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_typography_styles.html.erb (Duration: 0.3ms | Allocations: 131)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_card_styles.html.erb (Duration: 0.2ms | Allocations: 130)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_button_styles.html.erb (Duration: 0.3ms | Allocations: 211)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_form_styles.html.erb (Duration: 0.3ms | Allocations: 157)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/sessions/new.html.erb (Duration: 5.1ms | Allocations: 3111)
    app_1  | Completed 200 OK in 33ms (Views: 8.5ms | ActiveRecord: 0.0ms | Allocations: 10865)
    app_1  | 
    app_1  | 
    app_1  | Started POST "/api/auth" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:54:01 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  | Processing by ShopifyApp::SessionsController#create as HTML
    app_1  |   Parameters: {"authenticity_token"=>"[FILTERED]", "shop"=>"demo-store-mj.myshopify.com"}
    app_1  |   Shop Load (0.3ms)  SELECT "shops".* FROM "shops" WHERE "shops"."shopify_domain" = $1 LIMIT $2  [["shopify_domain", "demo-store-mj.myshopify.com"], ["LIMIT", 1]]
    app_1  |   CACHE Shop Load (0.0ms)  SELECT "shops".* FROM "shops" WHERE "shops"."shopify_domain" = $1 LIMIT $2  [["shopify_domain", "demo-store-mj.myshopify.com"], ["LIMIT", 1]]
    app_1  |   CACHE Shop Load (0.0ms)  SELECT "shops".* FROM "shops" WHERE "shops"."shopify_domain" = $1 LIMIT $2  [["shopify_domain", "demo-store-mj.myshopify.com"], ["LIMIT", 1]]
    app_1  | Redirected to https://demo-store-mj.myshopify.com/admin/oauth/authorize?client_id=61f6b66e9fd5f4994644fff850940c6c&scope=write_products&redirect_uri=https%3A%2F%2Fe70f-2402-e280-230d-553-634f-6a31-11e8-2e5d.ngrok-free.app%2Fapi%2Fauth%2Fcallback&state=m1LMd2UsX5zX4Sr&grant_options%5B%5D=
    app_1  | Completed 302 Found in 111ms (ActiveRecord: 2.9ms | Allocations: 80987)
    app_1  | 
    app_1  | 
    app_1  | Started GET "/api/auth/callback?code=dd8f8f60432f15bd4979f23cee8ff873&hmac=22932e69f59901c8092cbd3af9c188e62cf9fbde8891d8e9805eeae34c573b98&host=YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvZGVtby1zdG9yZS1tag&shop=demo-store-mj.myshopify.com&state=m1LMd2UsX5zX4Sr&timestamp=1702968842" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:54:02 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  | Processing by ShopifyApp::CallbackController#callback as HTML
    app_1  |   Parameters: {"code"=>"dd8f8f60432f15bd4979f23cee8ff873", "hmac"=>"22932e69f59901c8092cbd3af9c188e62cf9fbde8891d8e9805eeae34c573b98", "host"=>"YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvZGVtby1zdG9yZS1tag", "shop"=>"demo-store-mj.myshopify.com", "state"=>"m1LMd2UsX5zX4Sr", "timestamp"=>"1702968842"}
    app_1  |   Shop Load (0.2ms)  SELECT "shops".* FROM "shops" WHERE "shops"."shopify_domain" = $1 LIMIT $2  [["shopify_domain", "demo-store-mj.myshopify.com"], ["LIMIT", 1]]
    app_1  |   TRANSACTION (0.1ms)  BEGIN
    app_1  |   Shop Exists? (0.4ms)  SELECT 1 AS one FROM "shops" WHERE LOWER("shops"."shopify_domain") = LOWER($1) AND "shops"."id" != $2 LIMIT $3  [["shopify_domain", "demo-store-mj.myshopify.com"], ["id", 3], ["LIMIT", 1]]
    app_1  |   TRANSACTION (0.2ms)  COMMIT
    app_1  | [ActiveJob] Enqueued ShopifyApp::WebhooksManagerJob (Job ID: d6b2bd93-7b4e-43ee-8058-a9682e3f1fa7) to Async(default)
    app_1  | Redirected to https://admin.shopify.com/store/demo-store-mj/apps/61f6b66e9fd5f4994644fff850940c6c
    app_1  | Completed 302 Found in 603ms (ActiveRecord: 1.7ms | Allocations: 14049)
    app_1  | 
    app_1  | 
    app_1  | [ActiveJob] [ShopifyApp::WebhooksManagerJob] [d6b2bd93-7b4e-43ee-8058-a9682e3f1fa7] Performing ShopifyApp::WebhooksManagerJob (Job ID: d6b2bd93-7b4e-43ee-8058-a9682e3f1fa7) from Async(default) enqueued at 2023-12-19T06:54:03Z
    app_1  | [ActiveJob] [ShopifyApp::WebhooksManagerJob] [d6b2bd93-7b4e-43ee-8058-a9682e3f1fa7] Performed ShopifyApp::WebhooksManagerJob (Job ID: d6b2bd93-7b4e-43ee-8058-a9682e3f1fa7) from Async(default) in 2486.76ms
    app_1  | Started GET "/?embedded=1&hmac=5a397967d786c421d2f8e98587722105680eb0681fc08c01863de9b7282bb994&host=YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvZGVtby1zdG9yZS1tag&id_token=[FILTERED]&locale=en&prefetch=1&session=d4173f90230c87b91ee8eb38904ed8fe4c3fb3cff9e27f88a128b7326029db8f&shop=demo-store-mj.myshopify.com&timestamp=1702968846" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:54:06 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  | Processing by HomeController#index as HTML
    app_1  |   Parameters: {"embedded"=>"1", "hmac"=>"5a397967d786c421d2f8e98587722105680eb0681fc08c01863de9b7282bb994", "host"=>"YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvZGVtby1zdG9yZS1tag", "id_token"=>"[FILTERED]", "locale"=>"en", "prefetch"=>"1", "session"=>"d4173f90230c87b91ee8eb38904ed8fe4c3fb3cff9e27f88a128b7326029db8f", "shop"=>"demo-store-mj.myshopify.com", "timestamp"=>"1702968846"}
    app_1  |   Shop Load (0.2ms)  SELECT "shops".* FROM "shops" WHERE "shops"."shopify_domain" = $1 LIMIT $2  [["shopify_domain", "demo-store-mj.myshopify.com"], ["LIMIT", 1]]
    app_1  |   CACHE Shop Load (0.0ms)  SELECT "shops".* FROM "shops" WHERE "shops"."shopify_domain" = $1 LIMIT $2  [["shopify_domain", "demo-store-mj.myshopify.com"], ["LIMIT", 1]]
    app_1  |   Rendering text template
    app_1  |   Rendered text template (Duration: 0.0ms | Allocations: 10)
    app_1  | Completed 200 OK in 5ms (Views: 1.5ms | ActiveRecord: 0.2ms | Allocations: 3654)
    app_1  | 
    app_1  | 
    app_1  | Started GET "/index.jsx" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:54:06 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  | Started GET "/dev_embed.js" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:54:06 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  | Processing by HomeController#index as JS
    app_1  |   Parameters: {"path"=>"dev_embed"}
    app_1  | Redirected to https://e70f-2402-e280-230d-553-634f-6a31-11e8-2e5d.ngrok-free.app/api/auth
    app_1  | Filter chain halted as :check_shop_domain rendered or redirected
    app_1  | Completed 302 Found in 0ms (ActiveRecord: 0.0ms | Allocations: 181)
    app_1  | 
    app_1  | 
    app_1  | Processing by HomeController#index as */*
    app_1  |   Parameters: {"path"=>"index"}
    app_1  | Redirected to https://e70f-2402-e280-230d-553-634f-6a31-11e8-2e5d.ngrok-free.app/api/auth
    app_1  | Filter chain halted as :check_shop_domain rendered or redirected
    app_1  | Completed 302 Found in 0ms (ActiveRecord: 0.0ms | Allocations: 156)
    app_1  | 
    app_1  | 
    app_1  | Started GET "/api/auth" for 2402:e280:230d:553:634f:6a31:11e8:2e5d at 2023-12-19 06:54:06 +0000
    app_1  | Cannot render console from 2402:e280:230d:553:634f:6a31:11e8:2e5d! Allowed networks: 127.0.0.0/127.255.255.255, ::1
    app_1  | Processing by ShopifyApp::SessionsController#new as */*
    app_1  |   Rendering /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/sessions/new.html.erb
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_layout_styles.html.erb (Duration: 0.0ms | Allocations: 9)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_typography_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_card_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_button_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/partials/_form_styles.html.erb (Duration: 0.0ms | Allocations: 8)
    app_1  |   Rendered /usr/local/bundle/gems/shopify_app-21.8.1/app/views/shopify_app/sessions/new.html.erb (Duration: 1.2ms | Allocations: 649)
    app_1  | Completed 200 OK in 2ms (Views: 1.6ms | ActiveRecord: 0.0ms | Allocations: 1001)
    app_1  | 
    
    
    • shopify_api version: gem "shopify_api", "~> 13.3"
    • shopify_app version: gem "shopify_app", "~> 21.7"
    • Ruby version: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
    • Operating system: Ubuntu 20.04.6 LTS (64 bits)
    • Node version : v20.9.0
    • npm version : 10.2.4
    • rails version : Rails 7.0.8

    I am not able to see my UI although App is running in background

    Expected behavior

    I can see my UI and backend should work fine

    Actual behavior

    Unable to see UI

    Steps to reproduce the problem

    1. Make a App with shopify ruby template
    2. use postgres as database and use the above mentioned versions
    3. make a docker-compose.yml file at root
    4. make a build and run conatiner
    5. check logs

    Running Rake Commands w/ Docker Deployment on Heroku

    Issue summary

    I'm currently deploying to Heroku using the Docker container setup (Dockerfile & entrypoint.sh) contained in the template. However, when I try and run rake or shell commands on the resulting dyno, the current entrypoint.sh always results in the rails server command getting executed.

    # heroku run  bash
    Running bash on  <heroku app>... up, run.2013 (Basic)
    => Booting Puma
    => Rails 7.0.4.3 application starting in production
    => Run `bin/rails server --help` for more startup options
    Puma starting in single mode...
    * Puma version: 5.6.5 (ruby 3.1.4-p223) ("Birdie's Version")
    *  Min threads: 5
    *  Max threads: 5
    *  Environment: production
    *          PID: 7
    * Listening on http://0.0.0.0:42948
    Use Ctrl-C to stop
    ^C- Gracefully stopping, waiting for requests to finish
    === puma shutdown: 2023-07-15 14:53:29 +0000 ===
    - Goodbye!
    Exiting
    

    Expected behavior

    Rake & other shell commands should be executed

    Actual behavior

    Rails server continues to startup

    Steps to reproduce the problem

    1. Use existing app template to create a Shopify application.
    2. Deploy to Heroku
    3. Try and open a shell using heroku run bash

    Recommend Projects

    • React photo React

      A declarative, efficient, and flexible JavaScript library for building user interfaces.

    • Vue.js photo Vue.js

      🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

    • Typescript photo Typescript

      TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

    • TensorFlow photo TensorFlow

      An Open Source Machine Learning Framework for Everyone

    • Django photo Django

      The Web framework for perfectionists with deadlines.

    • D3 photo D3

      Bring data to life with SVG, Canvas and HTML. 📊📈🎉

    Recommend Topics

    • javascript

      JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

    • web

      Some thing interesting about web. New door for the world.

    • server

      A server is a program made to process requests and deliver data to clients.

    • Machine learning

      Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

    • Game

      Some thing interesting about game, make everyone happy.

    Recommend Org

    • Facebook photo Facebook

      We are working to build community through open source technology. NB: members must have two-factor auth.

    • Microsoft photo Microsoft

      Open source projects and samples from Microsoft.

    • Google photo Google

      Google ❤️ Open Source for everyone.

    • D3 photo D3

      Data-Driven Documents codes.