@@ -268,6 +268,7 @@ composer.json
268268deploy.sh
269269Dockerfile
270270jest.config.js
271+ local.ini
271272nginx-site.conf
272273package.json
273274phpcs.xml
@@ -280,6 +281,7 @@ schema.json
280281tailwind.config.js
281282TODO.md
282283webpack.mix.js
284+ www.conf
283285```
284286
285287# Files
@@ -87654,6 +87656,35 @@ echo "Running migrations..."
8765487656php artisan migrate --force
8765587657``````
8765687658
87659+ ## File: local.ini
87660+ ``````
87661+ ; Custom PHP settings for production
87662+
87663+ ; Error reporting
87664+ display_errors = Off
87665+ log_errors = On
87666+ error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
87667+
87668+ ; Performance and Security
87669+ expose_php = Off
87670+ max_execution_time = 60 ; Increased for potentially longer scripts
87671+ memory_limit = 256M ; Adjust based on your application's needs
87672+ post_max_size = 32M ; Max size for POST requests
87673+ upload_max_filesize = 32M ; Max upload file size
87674+ date.timezone = "UTC" ; Set your preferred timezone
87675+
87676+ ; Opcache (ensure opcache extension is enabled in Dockerfile)
87677+ opcache.enable=1
87678+ opcache.enable_cli=1
87679+ opcache.memory_consumption=128
87680+ opcache.interned_strings_buffer=8
87681+ opcache.max_accelerated_files=10000
87682+ opcache.revalidate_freq=0 ; Set to 0 for production (validate on every request if timestamp changed) or a higher value
87683+ opcache.validate_timestamps=1 ; Check timestamps in production
87684+ opcache.save_comments=1
87685+ opcache.fast_shutdown=1
87686+ ``````
87687+
8765787688## File: nginx-site.conf
8765887689``````
8765987690server {
@@ -87710,95 +87741,6 @@ server {
8771087741}
8771187742``````
8771287743
87713- ## File: render.yaml
87714- ``````yaml
87715- # render.yaml
87716- # Defines the infrastructure for deploying the Laravel application on Render
87717- # based on the provided schema.json.
87718- # Assumes CircleCI builds the Docker image, pushes it to a registry,
87719- # and then triggers a deploy on Render using a deploy hook.
87720- databases:
87721- - name: ecommerce-db # Name for your managed MySQL database
87722- plan: free # Example: "free", "starter", etc.
87723- # databaseName: laravel_ecommerce_db # Optional: specify the actual database name
87724- # user: db_user # Optional: specify the username
87725- # The schema provided lists postgresMajorVersion, not mysqlMajorVersion.
87726- # For MySQL, version is typically tied to the plan or a default.
87727- services:
87728- - type: web # Must be one of "web", "worker", "pserv", "cron" for serverService
87729- name: laravel-vue-ecommerce
87730- runtime: docker # Valid runtime for serverService
87731- autoDeploy: false # Boolean value
87732- healthCheckPath: /api/health # For web services
87733- # image: # Define if image is pre-built and pushed to a registry
87734- # url: registry.render.com/YOUR_RENDER_ORG_OR_USER/laravel-vue-ecommerce:latest
87735- envVars:
87736- - key: APP_NAME
87737- value: "Laravel Vue Ecommerce"
87738- - key: APP_ENV
87739- value: "production"
87740- - key: APP_DEBUG
87741- value: "false" # Env vars are strings
87742- - key: APP_URL
87743- value: "${RENDER_EXTERNAL_URL}" # Render injects this
87744- - key: ASSET_URL
87745- value: "${RENDER_EXTERNAL_URL}" # Render injects this
87746- - key: APP_KEY
87747- generateValue: true # Valid per envVarFromKeyValue schema
87748- - key: LOG_CHANNEL
87749- value: "stderr"
87750- # Database Connection
87751- - key: DB_CONNECTION # Tells Laravel to use the mysql driver
87752- value: "mysql"
87753- - key: DATABASE_URL # Laravel will parse this if DB_CONNECTION is set
87754- fromDatabase: # Valid per envVarFromDatabase schema
87755- name: ecommerce-db # Must match the name in the top-level 'databases' section
87756- property: connectionString # Provides the full database connection URL
87757- # Cache and Session
87758- - key: CACHE_DRIVER
87759- value: "file"
87760- - key: SESSION_DRIVER
87761- value: "file"
87762- # Stripe Keys (Set these as secrets in Render dashboard)
87763- - key: STRIPE_KEY
87764- sync: false # Valid per envVarFromKeyValue schema
87765- - key: STRIPE_SECRET
87766- sync: false
87767- - key: STRIPE_WEBHOOK_SECRET
87768- sync: false
87769- # Cashier Settings
87770- - key: CASHIER_CURRENCY
87771- value: "NOK"
87772- - key: CASHIER_CURRENCY_LOCALE
87773- value: "nb-NO"
87774- # Mailer Configuration (example, adjust as needed)
87775- - key: MAIL_MAILER
87776- value: "smtp"
87777- - key: MAIL_HOST
87778- value: "your_mail_host" # Set as secret or actual value
87779- - key: MAIL_PORT
87780- value: "587"
87781- - key: MAIL_USERNAME
87782- sync: false
87783- - key: MAIL_PASSWORD
87784- sync: false
87785- - key: MAIL_ENCRYPTION
87786- value: "tls"
87787- - key: MAIL_FROM_ADDRESS
87788- value: "hello@example.com"
87789- - key: MAIL_FROM_NAME
87790- value: "${APP_NAME}"
87791- # Start command: runs our deploy script, then starts the main services.
87792- # Assumes the base Docker image (ric_harvey/nginx-php-fpm) has /start.sh as its CMD,
87793- # which typically runs supervisord to manage Nginx and PHP-FPM.
87794- startCommand: "/usr/local/bin/deploy.sh && /start.sh"
87795- # Persistent disk for Laravel storage
87796- disk: # Valid per serverService schema, referencing "disk" definition
87797- name: laravel-storage # Name for the persistent disk
87798- mountPath: /var/www/html/storage # Mount path inside the container
87799- sizeGB: 1 # Size of the disk in GB, integer
87800- ``````
87801-
8780287744## File: schema.json
8780387745``````json
8780487746{
@@ -88605,81 +88547,180 @@ The project uses a modern stack (Laravel 10, Vue 3) and follows generally good p
8860588547- [ ] Clarify the meaning of "bot" in the initial project description. If there's specific automated functionality intended, it needs to be reviewed.
8860688548``````
8860788549
88550+ ## File: www.conf
88551+ ``````
88552+ [www]
88553+ user = www-data
88554+ group = www-data
88555+ listen = /var/run/php-fpm.sock
88556+ ;listen = 127.0.0.1:9000
88557+ listen.owner = www-data
88558+ listen.group = www-data
88559+ listen.mode = 0660
88560+
88561+ pm = dynamic
88562+ pm.max_children = 5
88563+ pm.start_servers = 2
88564+ pm.min_spare_servers = 1
88565+ pm.max_spare_servers = 3
88566+ pm.max_requests = 500
88567+
88568+ chdir = /var/www/html
88569+
88570+ catch_workers_output = yes
88571+ php_flag[display_errors] = off
88572+ php_admin_value[error_log] = /var/log/fpm-php.www.log
88573+ php_admin_flag[log_errors] = on
88574+ ``````
88575+
88576+ ## File: render.yaml
88577+ ``````yaml
88578+ # render.yaml
88579+ # Defines the infrastructure for deploying the Laravel application on Render
88580+ # based on the provided schema.json.
88581+ # Assumes CircleCI builds the Docker image, pushes it to a registry,
88582+ # and then triggers a deploy on Render using a deploy hook.
88583+ databases:
88584+ - name: ecommerce-db # Name for your managed MySQL database
88585+ plan: free # Example: "free", "starter", etc.
88586+ # databaseName: laravel_ecommerce_db # Optional: specify the actual database name
88587+ # user: db_user # Optional: specify the username
88588+ # The schema provided lists postgresMajorVersion, not mysqlMajorVersion.
88589+ # For MySQL, version is typically tied to the plan or a default.
88590+ services:
88591+ - type: web # Must be one of "web", "worker", "pserv", "cron" for serverService
88592+ name: laravel-vue-ecommerce
88593+ runtime: docker # Valid runtime for serverService
88594+ autoDeploy: false # Boolean value
88595+ healthCheckPath: /api/health # For web services
88596+ # image: # Define if image is pre-built and pushed to a registry
88597+ # url: registry.render.com/YOUR_RENDER_ORG_OR_USER/laravel-vue-ecommerce:latest
88598+ envVars:
88599+ - key: APP_NAME
88600+ value: "Laravel Vue Ecommerce"
88601+ - key: APP_ENV
88602+ value: "production"
88603+ - key: APP_DEBUG
88604+ value: "false" # Env vars are strings
88605+ - key: APP_URL
88606+ value: "${RENDER_EXTERNAL_URL}" # Render injects this
88607+ - key: ASSET_URL
88608+ value: "${RENDER_EXTERNAL_URL}" # Render injects this
88609+ - key: APP_KEY
88610+ generateValue: true # Valid per envVarFromKeyValue schema
88611+ - key: LOG_CHANNEL
88612+ value: "stderr"
88613+ # Database Connection
88614+ - key: DB_CONNECTION # Tells Laravel to use the mysql driver
88615+ value: "mysql"
88616+ - key: DATABASE_URL # Laravel will parse this if DB_CONNECTION is set
88617+ fromDatabase: # Valid per envVarFromDatabase schema
88618+ name: ecommerce-db # Must match the name in the top-level 'databases' section
88619+ property: connectionString # Provides the full database connection URL
88620+ # Cache and Session
88621+ - key: CACHE_DRIVER
88622+ value: "file"
88623+ - key: SESSION_DRIVER
88624+ value: "file"
88625+ # Stripe Keys (Set these as secrets in Render dashboard)
88626+ - key: STRIPE_KEY
88627+ sync: false # Valid per envVarFromKeyValue schema
88628+ - key: STRIPE_SECRET
88629+ sync: false
88630+ - key: STRIPE_WEBHOOK_SECRET
88631+ sync: false
88632+ # Cashier Settings
88633+ - key: CASHIER_CURRENCY
88634+ value: "NOK"
88635+ - key: CASHIER_CURRENCY_LOCALE
88636+ value: "nb-NO"
88637+ # Mailer Configuration (example, adjust as needed)
88638+ - key: MAIL_MAILER
88639+ value: "smtp"
88640+ - key: MAIL_HOST
88641+ value: "your_mail_host" # Set as secret or actual value
88642+ - key: MAIL_PORT
88643+ value: "587"
88644+ - key: MAIL_USERNAME
88645+ sync: false
88646+ - key: MAIL_PASSWORD
88647+ sync: false
88648+ - key: MAIL_ENCRYPTION
88649+ value: "tls"
88650+ - key: MAIL_FROM_ADDRESS
88651+ value: "hello@example.com"
88652+ - key: MAIL_FROM_NAME
88653+ value: "${APP_NAME}"
88654+ # Start command: The Docker image's CMD ["/start.sh"] will be used by default.
88655+ # The /start.sh script from richarvey/nginx-php-fpm will execute our /scripts/00-laravel-deploy.sh
88656+ # (because ENV RUN_SCRIPTS 1 is set) and then start Nginx & PHP-FPM.
88657+ # Thus, no explicit startCommand override is needed here.
88658+ # Persistent disk for Laravel storage
88659+ disk: # Valid per serverService schema, referencing "disk" definition
88660+ name: laravel-storage # Name for the persistent disk
88661+ mountPath: /var/www/html/storage # Mount path inside the container
88662+ sizeGB: 1 # Size of the disk in GB, integer
88663+ ``````
88664+
8860888665## File: Dockerfile
8860988666``````dockerfile
8861088667# Stage 1: Compile Frontend Assets
8861188668FROM node:20-alpine AS node_builder
8861288669
8861388670WORKDIR /app/frontend
8861488671
88615- # Copy package files and install dependencies
88616- COPY package.json package-lock.json* ./
88617- # Copy build configuration files
88618- COPY webpack.mix.js tailwind.config.js postcss.config.js* .babelrc* ./
88619- # Ensure postcss.config.js and .babelrc are optional by using *
88672+ # Copy package files and essential build configuration
88673+ COPY package.json package-lock.json* webpack.mix.js tailwind.config.js postcss.config.js* .babelrc* ./
88674+ # Ensure postcss.config.js and .babelrc are optional by using * in case they don't exist
8862088675
88621- # Install dependencies for building assets
88622- # Using npm ci for cleaner installs if package-lock.json is present and up-to-date
88623- RUN npm ci --production
88676+ # Install all dependencies (including devDependencies like laravel-mix)
88677+ RUN npm ci
8862488678
88625- # Copy frontend source code
88679+ # Copy frontend source code (js, css, images, etc.)
8862688680COPY resources/js ./resources/js
8862788681COPY resources/css ./resources/css
8862888682COPY resources/img ./resources/img
88629- # Add other resource directories if you have them (e.g., resources/fonts)
88683+ # Add other relevant resource directories if needed
8863088684
88631- # Compile assets
88685+ # Compile assets for production
8863288686RUN npm run production
8863388687
88634- # Stage 2: Setup PHP Application Environment
88635- FROM ric_harvey/nginx-php-fpm:3.1.6 AS app
88688+ # Stage 2: Setup PHP Application Environment using richarvey/nginx-php-fpm
88689+ FROM richarvey/nginx-php-fpm:3.1.6 AS app
88690+
88691+ # Set Laravel Environment Variables as per the article
88692+ ENV APP_ENV production
88693+ ENV APP_DEBUG false
88694+ ENV LOG_CHANNEL stderr
88695+ ENV APP_KEY ${APP_KEY}
88696+ ENV SKIP_COMPOSER 1
88697+ ENV WEBROOT /var/www/html/public
88698+ ENV PHP_ERRORS_STDERR 1 # Send PHP errors to stderr for Docker logging
88699+ ENV RUN_SCRIPTS 1 # Enable execution of scripts in /scripts directory
88700+ ENV REAL_IP_HEADER 1 # If behind a proxy, trust X-Forwarded-For
88701+ ENV COMPOSER_ALLOW_SUPERUSER 1 # Allow composer to run as root if needed by scripts
8863688702
8863788703# Set working directory
8863888704WORKDIR /var/www/html
8863988705
88640- # Install system dependencies and PHP extensions
88641- # The ric_harvey/nginx-php-fpm image should have most common extensions.
88642- # We'll add pdo_mysql, gd, zip, bcmath, exif, opcache, intl if they are not present.
88643- # This often requires root access, then dropping back to www-data.
88644- # The exact commands depend on the base image's package manager (apk for Alpine).
88645- USER root
88646- RUN apk add --no-cache \
88647- libzip-dev \
88648- libpng-dev \
88649- libjpeg-turbo-dev \
88650- freetype-dev \
88651- && docker-php-ext-configure gd --with-freetype --with-jpeg \
88652- && docker-php-ext-install -j$(nproc) gd pdo_mysql zip bcmath exif opcache intl \
88653- && apk del libzip-dev libpng-dev libjpeg-turbo-dev freetype-dev \
88654- && rm -rf /var/cache/apk/*
88655-
88656- # Install Composer globally
88657- COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
88658-
88659- # Copy application files (respecting .dockerignore)
88706+ # Copy all application files
8866088707COPY . .
8866188708
8866288709# Copy compiled assets from the node_builder stage
88663- COPY --chown=www-data:www-data --from=node_builder /app/frontend/public ./public
88664-
88665- # Set permissions for Laravel storage and bootstrap cache
88666- # Ensure these directories exist before chown/chmod if copying doesn't create them fully.
88667- RUN mkdir -p storage/framework/sessions storage/framework/cache/data storage/framework/views storage/logs \
88668- && chown -R www-data:www-data storage bootstrap/cache \
88669- && chmod -R 775 storage bootstrap/cache
88710+ COPY --from=node_builder /app/frontend/public ./public
8867088711
88671- # Copy Nginx site configuration
88672- # The ric_harvey image might use /etc/nginx/conf.d/default.conf or similar.
88673- # We'll assume /etc/nginx/sites-available/default and ensure it's linked or directly used.
88712+ # Copy our Nginx site configuration to the standard location for richarvey images
8867488713COPY nginx-site.conf /etc/nginx/sites-available/default
88675- # If sites-enabled is used: RUN ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
8867688714
88677- # Copy and set permissions for the deploy script
88678- COPY deploy.sh /usr/local/bin/deploy.sh
88679- RUN chmod +x /usr/local/bin/deploy.sh
88715+ # Copy our deploy script to the location where richarvey image expects to run scripts
88716+ # Ensure deploy.sh has necessary commands (composer install, migrations, cache)
88717+ RUN mkdir -p /scripts
88718+ COPY deploy.sh /scripts/00-laravel-deploy.sh
88719+ RUN chmod +x /scripts/00-laravel-deploy.sh
8868088720
88681- # Expose port 80
88682- EXPOSE 80
88721+ # The base image (richarvey/nginx-php-fpm) handles starting Nginx, PHP-FPM,
88722+ # and running scripts from /scripts. Its default CMD is /start.sh.
88723+ CMD ["/start.sh"]
8868388724``````
8868488725
8868588726## File: .circleci/config.yml
@@ -88860,7 +88901,7 @@ workflows:
8886088901 "@testing-library/vue": "7.0.0",
8886188902 "@vue/vue3-jest": "29.2.6",
8886288903 "autoprefixer": "10.4.21",
88863- "axios": "1.6.8 ",
88904+ "axios": "1.9.0 ",
8886488905 "babel-core": "7.0.0-bridge.0",
8886588906 "babel-jest": "29.7.0",
8886688907 "global-jsdom": "9.1.0",
@@ -88871,7 +88912,7 @@ workflows:
8887188912 "lodash": "4.17.21",
8887288913 "postcss": "8.4.40",
8887388914 "prettier": "3.5.3",
88874- "tailwindcss": "3.4.11 ",
88915+ "tailwindcss": "3.4.17 ",
8887588916 "vue-loader": "17.4.2"
8887688917 },
8887788918 "dependencies": {
0 commit comments