This commit is contained in:
Andras Bacsai 2026-04-27 10:51:15 +02:00 committed by GitHub
commit 96bfc14543
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 829 additions and 105 deletions

View file

@ -60,7 +60,7 @@ ### Huge Sponsors
* [MVPS](https://www.mvps.net?ref=coolify.io) - Cheap VPS servers at the highest possible quality
* [SerpAPI](https://serpapi.com?ref=coolify.io) - Google Search API — Scrape Google and other search engines from our fast, easy, and complete API
* [ScreenshotOne](https://screenshotone.com?ref=coolify.io) - Screenshot API for devs
*
* [PrivateAlps](https://privatealps.net?ref=coolify.io) - Cloud Services Provider, VPS, servers Infrastructure for people who care about privacy and control
### Big Sponsors
@ -151,6 +151,10 @@ ### Small Sponsors
<a href="https://capgo.app/?utm_source=coolify.io"><img width="60px" alt="Cap-go" src="https://github.com/cap-go.png"/></a>
<a href="https://interviewpal.com/?utm_source=coolify.io"><img width="60px" alt="InterviewPal" src="/public/svgs/interviewpal.svg"/></a>
<a href="https://transcript.lol/?utm_source=coolify.io"><img width="60px" alt="Transcript LOL" src="https://transcript.lol/logo.png"/></a>
<a href="https://youstable.com/?utm_source=coolify.io"><img width="60px" alt="YouStable" src="https://github.com/youstable.png"/></a>
<a href="https://github.com/mindedtech?utm_source=coolify.io"><img width="60px" alt="MindedTech" src="https://github.com/mindedtech.png"/></a>
<a href="https://netrouting.com/?utm_source=coolify.io"><img width="60px" alt="NetRouting" src="https://github.com/netroutingcom.png"/></a>
<a href="https://github.com/parsecph?utm_source=coolify.io"><img width="60px" alt="ParsecPH" src="https://github.com/parsecph.png"/></a>
...and many more at [GitHub Sponsors](https://github.com/sponsors/coollabsio)

View file

@ -3532,10 +3532,10 @@ function wireNavigate(): string
try {
$settings = instanceSettings();
// Return wire:navigate.hover for SPA navigation with prefetching, or empty string if disabled
return ($settings->is_wire_navigate_enabled ?? true) ? 'wire:navigate.hover' : '';
// Return wire:navigate for SPA navigation with prefetching, or empty string if disabled
return ($settings->is_wire_navigate_enabled ?? true) ? 'wire:navigate' : '';
} catch (Exception $e) {
return 'wire:navigate.hover';
return 'wire:navigate';
}
}

View file

@ -2,7 +2,7 @@
return [
'coolify' => [
'version' => '4.0.0-beta.474',
'version' => '4.0.0',
'helper_version' => '1.0.13',
'realtime_version' => '1.0.13',
'self_hosted' => env('SELF_HOSTED', true),

View file

@ -1,7 +1,7 @@
{
"coolify": {
"v4": {
"version": "4.0.0-beta.474"
"version": "4.0.0"
},
"nightly": {
"version": "4.0.0"

BIN
public/svgs/cap-captcha.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -1,4 +1,5 @@
<div {{ $attributes->merge(['class' => 'group']) }}>
<div x-data="{ open: false }" @click.stop="open = !open" @click.outside="open = false"
{{ $attributes->merge(['class' => 'group']) }}>
<div class="info-helper">
@isset($icon)
{{ $icon }}
@ -10,7 +11,7 @@
@endisset
</div>
<div class="info-helper-popup">
<div class="info-helper-popup" :class="{ 'block': open }">
<div class="p-4">
{!! $helper !!}
</div>

650
svgs/jitsi.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 35 KiB

View file

@ -6,7 +6,7 @@
services:
beszel-agent:
image: 'henrygd/beszel-agent:0.18.4' # Released on 21 Feb 2026
image: 'henrygd/beszel-agent:0.18.7' # Released on 6 April 2026
network_mode: host # Network stats graphs won't work if agent cannot access host system network stack
environment:
# Required
@ -28,4 +28,4 @@ services:
interval: 60s
timeout: 20s
retries: 10
start_period: 5s
start_period: 5s

View file

@ -9,7 +9,7 @@
# Add the public Key in "Key" env variable and token in the "Token" variable below (These are obtained from Beszel UI)
services:
beszel:
image: 'henrygd/beszel:0.18.4' # Released on 21 Feb 2026
image: 'henrygd/beszel:0.18.7' # Released on 6 April 2026
environment:
- SERVICE_URL_BESZEL_8090
- CONTAINER_DETAILS=${CONTAINER_DETAILS:-true}
@ -24,7 +24,7 @@ services:
retries: 10
start_period: 5s
beszel-agent:
image: 'henrygd/beszel-agent:0.18.4' # Released on 21 Feb 2026
image: 'henrygd/beszel-agent:0.18.7' # Released on 6 April 2026
network_mode: host # Network stats graphs won't work if agent cannot access host system network stack
environment:
# Required
@ -46,4 +46,4 @@ services:
interval: 60s
timeout: 20s
retries: 10
start_period: 5s
start_period: 5s

View file

@ -1,3 +1,4 @@
# ignore: true
# documentation: https://cal.com/docs/developing/introduction
# slogan: Scheduling infrastructure for everyone.
# category: productivity

View file

@ -0,0 +1,34 @@
# documentation: https://capjs.js.org/guide/
# slogan: The self-hosted CAPTCHA for the modern web.
# category: security
# tags: captcha,security,privacy,proof-of-work
# logo: svgs/cap-captcha.png
# port: 3000
services:
cap:
image: tiago2/cap:3.0.4 # Released on 22nd April 2026
environment:
- SERVICE_URL_CAP_3000
- ADMIN_KEY=$SERVICE_PASSWORD_ADMIN
- REDIS_URL=redis://valkey:6379
healthcheck:
test: ["CMD", "bun", "-e", "fetch('http://localhost:3000').then(r => { if (!r.ok) process.exit(1) }).catch(() => process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3
start_period: 5s
depends_on:
valkey:
condition: service_healthy
valkey:
image: valkey/valkey:9-alpine
volumes:
- valkey-data:/data
command: valkey-server --save 60 1 --loglevel warning --maxmemory-policy noeviction
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5

View file

@ -1,127 +1,139 @@
# ignore: true
# documentation: https://jitsi.github.io/handbook/docs/intro
# documentation: https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker/
# slogan: Self-hosted Jitsi Meet — open-source video conferencing platform
# tags: jitsi,video,conference,webrtc,meeting,self-hosted
# category: productivity
# slogan: World's easiest way to add meetings to your apps
# logo: svgs/jitsi.svg
# tags: video, conferencing, meetings, communication, open-source
# port: 80
services:
jitsi-web:
image: "jitsi/web:${JITSI_IMAGE_VERSION:-unstable}"
container_name: jitsi-web
image: "jitsi/web:stable-10888"
restart: unless-stopped
ports:
- "8001:80"
- "8443:443"
volumes:
- ~/.jitsi-meet-cfg/web:/config:Z
- ~/.jitsi-meet-cfg/web/crontabs:/var/spool/cron/crontabs:Z
- ~/.jitsi-meet-cfg/transcripts:/usr/share/jitsi-meet/transcripts:Z
environment:
- SERVICE_URL_JITSI
- PUBLIC_URL=$SERVICE_URL_JITSI
- JITSI_IMAGE_VERSION=unstable
- JIBRI_RECORDER_PASSWORD=$SERVICE_PASSWORD_JITSI
- JIBRI_XMPP_PASSWORD=$SERVICE_PASSWORD_JITSI
- JICOFO_AUTH_PASSWORD=$SERVICE_PASSWORD_JITSI
- JIGASI_XMPP_PASSWORD=$SERVICE_PASSWORD_JITSI
- JVB_AUTH_PASSWORD=$SERVICE_PASSWORD_JITSI
- TZ=UTC
- ENABLE_AUTH=0
- ENABLE_GUESTS=1
- ENABLE_LETSENCRYPT=0
- ENABLE_HTTP_REDIRECT=0
- DISABLE_HTTPS=1
- XMPP_DOMAIN=meet.jitsi
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
- XMPP_GUEST_DOMAIN=guest.meet.jitsi
- XMPP_MUC_DOMAIN=conference.meet.jitsi
- XMPP_INTERNAL_MUC_DOMAIN=internal.auth.meet.jitsi
- XMPP_BOSH_URL_BASE=http://prosody:5280
- JVB_BREWERY_MUC=jvbbrewery
- JICOFO_COMPONENT_SECRET=${SERVICE_PASSWORD_JICOFO}
- JICOFO_AUTH_PASSWORD=${SERVICE_PASSWORD_JICOFO}
- JVB_AUTH_PASSWORD=${SERVICE_PASSWORD_JVB}
- TZ=${TZ:-UTC}
depends_on:
- prosody
- jicofo
- jvb
volumes:
- jitsi-web:/config
networks:
meet.jitsi:
aliases:
- meet.jitsi
depends_on:
- jvb
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 2s
interval: 5s
timeout: 10s
retries: 15
prosody:
image: "jitsi/prosody:${JITSI_IMAGE_VERSION:-unstable}"
expose:
- '5222'
- '5347'
- '5280'
container_name: jitsi-xmpp
image: "jitsi/prosody:stable-10888"
restart: unless-stopped
volumes:
- ~/.jitsi-meet-cfg/prosody/config:/config:Z
- ~/.jitsi-meet-cfg/prosody/prosody-plugins-custom:/prosody-plugins-custom:Z
environment:
- JICOFO_AUTH_PASSWORD
- JVB_AUTH_PASSWORD
- AUTH_TYPE=internal
- ENABLE_AUTH=0
- ENABLE_GUESTS=1
- XMPP_DOMAIN=meet.jitsi
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
- XMPP_GUEST_DOMAIN=guest.meet.jitsi
- XMPP_MUC_DOMAIN=conference.meet.jitsi
- XMPP_INTERNAL_MUC_DOMAIN=internal.auth.meet.jitsi
- JICOFO_COMPONENT_SECRET=${SERVICE_PASSWORD_JICOFO}
- JICOFO_AUTH_PASSWORD=${SERVICE_PASSWORD_JICOFO}
- JVB_AUTH_PASSWORD=${SERVICE_PASSWORD_JVB}
- PUBLIC_URL=$SERVICE_URL_JITSI
- TZ
- TZ=${TZ:-UTC}
- LOG_LEVEL=${LOG_LEVEL:-info}
volumes:
- jitsi-prosody:/config
networks:
meet.jitsi:
aliases:
- xmpp.meet.jitsi
- auth.meet.jitsi
- guest.meet.jitsi
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5280/http-bind"]
interval: 2s
interval: 5s
timeout: 10s
retries: 15
jicofo:
image: "jitsi/jicofo:${JITSI_IMAGE_VERSION:-unstable}"
container_name: jitsi-jicofo
image: "jitsi/jicofo:stable-10888"
restart: unless-stopped
volumes:
- ~/.jitsi-meet-cfg/jicofo:/config:Z
environment:
- AUTH_TYPE=internal
- ENABLE_AUTH=0
- XMPP_DOMAIN=meet.jitsi
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
- XMPP_INTERNAL_MUC_DOMAIN=internal.auth.meet.jitsi
- XMPP_MUC_DOMAIN=conference.meet.jitsi
- XMPP_SERVER=prosody
- JICOFO_AUTH_PASSWORD
- TZ
- JICOFO_COMPONENT_SECRET=${SERVICE_PASSWORD_JICOFO}
- JICOFO_AUTH_PASSWORD=${SERVICE_PASSWORD_JICOFO}
- JVB_BREWERY_MUC=jvbbrewery
- JICOFO_ENABLE_HEALTH_CHECKS=1
- TZ=${TZ:-UTC}
depends_on:
- prosody
volumes:
- jitsi-jicofo:/config
networks:
meet.jitsi:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8888/about/health"]
interval: 2s
interval: 5s
timeout: 10s
retries: 15
jvb:
image: "jitsi/jvb:${JITSI_IMAGE_VERSION:-unstable}"
container_name: jitsi-jvb
image: "jitsi/jvb:stable-10888"
restart: unless-stopped
expose:
- '10000:10000/udp'
- '8080:8080'
- '10000'
volumes:
- ~/.jitsi-meet-cfg/jvb:/config:Z
ports:
- "10000:10000/udp"
environment:
- JVB_ADVERTISE_IPS
- JVB_AUTH_PASSWORD
- PUBLIC_URL=$SERVICE_URL_JITSI
- TZ
- XMPP_SERVER=prosody
- XMPP_DOMAIN=meet.jitsi
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
- XMPP_INTERNAL_MUC_DOMAIN=internal.auth.meet.jitsi
- XMPP_MUC_DOMAIN=conference.meet.jitsi
- JVB_AUTH_USER=jvb
- JVB_AUTH_PASSWORD=${SERVICE_PASSWORD_JVB}
- JVB_BREWERY_MUC=jvbbrewery
- JVB_PORT=10000
- JVB_ADVERTISE_IPS=${JVB_ADVERTISE_IPS:-} #Optional: set your public IP only if STUN auto-detection fails or the server is behind NAT / multiple interfaces
- JVB_STUN_SERVERS=${JVB_STUN_SERVERS:-stun.l.google.com:19302}
- PUBLIC_URL=$SERVICE_URL_JITSI
- TZ=${TZ:-UTC}
depends_on:
- prosody
volumes:
- jitsi-jvb:/config
networks:
meet.jitsi:
labels:
- "traefik.enable=true"
- "traefik.udp.routers.my-udp-router.entrypoints=video"
- "traefik.udp.routers.my-udp-router.service=my-udp-service"
- "traefik.udp.services.my-udp-service.loadbalancer.server.port=10000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/about/health"]
interval: 2s
interval: 5s
timeout: 10s
retries: 15
networks:
meet.jitsi:
volumes:
jitsi-web:
jitsi-xmpp:
jitsi-jicofo:
jitsi-jvb:

View file

@ -88,6 +88,11 @@ services:
environment:
<<: *app-env
depends_on: *langfuse-depends-on
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3030/api/health"]
interval: 30s
timeout: 10s
retries: 3
postgres:
image: postgres:17-alpine

View file

@ -10,7 +10,7 @@ services:
depends_on:
postgres:
condition: service_healthy
entrypoint: ["sh", "-c", "npm run cli db seed -- --swe && npm start"]
entrypoint: ["sh", "-c", "npm run cli db seed -- --swe && npm run alteration deploy latest && npm start"]
environment:
- SERVICE_URL_LOGTO
- TRUST_PROXY_HEADER=1

View file

@ -1,7 +1,7 @@
# ignore: true
# documentation: https://docs.plane.so/self-hosting/methods/docker-compose
# slogan: The open source project management tool
# category: productivity
# port: 80
# tags: plane,project-management,tool,open,source,api,nextjs,redis,postgresql,django,pm
# logo: svgs/plane.svg
@ -30,6 +30,12 @@ x-aws-s3-env: &aws-s3-env
AWS_S3_ENDPOINT_URL: ${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
x-proxy-env: &proxy-env
APP_DOMAIN: ${SERVICE_URL_PLANE}
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
SITE_ADDRESS: ${SITE_ADDRESS:-:80}
x-mq-env: &mq-env # RabbitMQ Settings
RABBITMQ_HOST: plane-mq
RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
@ -40,9 +46,10 @@ x-mq-env: &mq-env # RabbitMQ Settings
x-live-env: &live-env
API_BASE_URL: ${API_BASE_URL:-http://api:8000}
LIVE_SERVER_SECRET_KEY: $SERVICE_PASSWORD_64_LIVESECRET
x-app-env: &app-env
APP_RELEASE: ${APP_RELEASE:-v1.0.0}
APP_RELEASE: ${APP_RELEASE:-v1.3.0}
WEB_URL: ${SERVICE_URL_PLANE}
DEBUG: ${DEBUG:-0}
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-http://localhost}
@ -53,16 +60,20 @@ x-app-env: &app-env
AMQP_URL: amqp://${SERVICE_USER_RABBITMQ}:${SERVICE_PASSWORD_RABBITMQ}@plane-mq:${RABBITMQ_PORT:-5672}/plane
API_KEY_RATE_LIMIT: ${API_KEY_RATE_LIMIT:-60/minute}
MINIO_ENDPOINT_SSL: ${MINIO_ENDPOINT_SSL:-0}
LIVE_SERVER_SECRET_KEY: $SERVICE_PASSWORD_64_LIVESECRET
services:
proxy:
image: artifacts.plane.so/makeplane/plane-proxy:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-proxy:${APP_RELEASE:-v1.3.0}
environment:
- SERVICE_URL_PLANE
- APP_DOMAIN=${SERVICE_URL_PLANE}
- SITE_ADDRESS=:80
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
- BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
volumes:
- proxy_config:/config
- proxy_data:/data
depends_on:
- web
- api
@ -74,8 +85,9 @@ services:
interval: 2s
timeout: 10s
retries: 15
web:
image: artifacts.plane.so/makeplane/plane-frontend:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-frontend:${APP_RELEASE:-v1.3.0}
depends_on:
- api
- worker
@ -86,7 +98,7 @@ services:
retries: 15
space:
image: artifacts.plane.so/makeplane/plane-space:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-space:${APP_RELEASE:-v1.3.0}
depends_on:
- api
- worker
@ -98,7 +110,7 @@ services:
retries: 15
admin:
image: artifacts.plane.so/makeplane/plane-admin:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-admin:${APP_RELEASE:-v1.3.0}
depends_on:
- api
- web
@ -109,13 +121,12 @@ services:
retries: 15
live:
image: artifacts.plane.so/makeplane/plane-live:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-live:${APP_RELEASE:-v1.3.0}
environment:
<<: [*live-env, *redis-env]
depends_on:
- api
- web
- plane-redis
healthcheck:
test: ["CMD", "echo", "hey whats up"]
interval: 2s
@ -123,12 +134,12 @@ services:
retries: 15
api:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.0}
command: ./bin/docker-entrypoint-api.sh
volumes:
- logs_api:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *mq-env]
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- plane-db
- plane-redis
@ -140,12 +151,12 @@ services:
retries: 15
worker:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.0}
command: ./bin/docker-entrypoint-worker.sh
volumes:
- logs_worker:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *mq-env]
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- api
- plane-db
@ -158,12 +169,12 @@ services:
retries: 15
beat-worker:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.0}
command: ./bin/docker-entrypoint-beat.sh
volumes:
- logs_beat-worker:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *mq-env]
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- api
- plane-db
@ -176,13 +187,13 @@ services:
retries: 15
migrator:
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.0.0}
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.0}
restart: "no"
command: ./bin/docker-entrypoint-migrator.sh
volumes:
- logs_migrator:/code/plane/logs
environment:
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *mq-env]
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
depends_on:
- plane-db
- plane-redis
@ -202,7 +213,7 @@ services:
retries: 10
plane-redis:
image: valkey/valkey:7.2.5-alpine
image: valkey/valkey:7.2.11-alpine
volumes:
- redisdata:/data
healthcheck:
@ -213,7 +224,6 @@ services:
plane-mq:
image: rabbitmq:3.13.6-management-alpine
restart: always
environment:
<<: *mq-env
volumes:

View file

@ -32,15 +32,14 @@ services:
- SERVICE_URL_RALLLY_3000
- DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@rallly_db:5432/${POSTGRES_DB:-rallly}
- SECRET_PASSWORD=${SERVICE_PASSWORD_64_RALLLY}
- NEXT_PUBLIC_BASE_URL=https://${SERVICE_URL_RALLLY}
- NEXT_PUBLIC_BASE_URL=${SERVICE_URL_RALLLY}
- ALLOWED_EMAILS=${ALLOWED_EMAILS}
- SUPPORT_EMAIL=${SUPPORT_EMAIL:-support@example.com}
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=${SMTP_PORT}
- SMTP_SECURE=${SMTP_SECURE}
- SMTP_SECURE=${SMTP_SECURE:-false}
- SMTP_USER=${SMTP_USER}
- SMTP_PWD=${SMTP_PWD}
- SMTP_TLS_ENABLED=${SMTP_TLS_ENABLED}
healthcheck:
test: ["CMD-SHELL", "bash -c ':> /dev/tcp/127.0.0.1/3000' || exit 1"]
interval: 5s

View file

@ -53,7 +53,7 @@ services:
interval: 2s
timeout: 5s
retries: 10
start_period: 10s
start_period: 30s
depends_on:
postgres:
condition: service_healthy
@ -102,7 +102,15 @@ services:
depends_on:
twenty:
condition: service_healthy
healthcheck:
test:
- CMD-SHELL
- "ps aux | grep 'dist/queue-worker/queue-worker' | grep -v grep || exit 1"
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
postgres:
image: postgres:16-alpine
environment:

View file

@ -1,7 +1,7 @@
{
"coolify": {
"v4": {
"version": "4.0.0-beta.474"
"version": "4.0.0"
},
"nightly": {
"version": "4.0.0"