add gitea ci
ci / build (push) Failing after 26s Details
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s Details

This commit is contained in:
Chris Grimmett 2024-03-28 23:28:02 -08:00
parent 7eed008f13
commit 0fd947c78f
96 changed files with 20935 additions and 9195 deletions

View File

@ -1,5 +1,8 @@
Dockerfile Dockerfile
*.dockerfile
.dockerignore .dockerignore
.gitignore
*~
node_modules node_modules
npm-debug.log npm-debug.log
README.md README.md

View File

@ -0,0 +1,32 @@
name: ci
on:
push:
branches:
- 'main'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Check out code
# idk if I need this. is it automatically gathered from the act runner?
# with:
# repository: https://gitea.futureporn.net/futureporn/fp
- uses: mr-smithers-excellent/docker-build-push@v6
name: Build & push fp/next Docker image
with:
image: gitea.futureporn.net/futureporn/next
tags: latest
# which 'registry:' version do I need?
registry: https://gitea.futureporn.net
# registry: https://gitea.futureporn.net/futureporn
dockerfile: packages/next/Dockerfile
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# docker push gitea.futureporn.net/cj_clippy/link2cid:latest

42
Makefile Normal file
View File

@ -0,0 +1,42 @@
include .env
secrets:
kubectl delete secret link2cid --ignore-not-found
kubectl create secret generic link2cid \
--from-literal=apiKey=${LINK2CID_API_KEY}
kubectl delete secret vultr
kubectl create secret generic vultr \
--from-literal=vultr=${VULTR_CONTAINER_REGISTRY_USERNAME}
# --from-literal=sessionSecret=$(SESSION_SECRET) \
# --from-literal=twitchClientId=$(TWITCH_CLIENT_ID) \
# --from-literal=twitchClientSecret=$(TWITCH_CLIENT_SECRET) \
# --from-literal=gumroadClientId=$(GUMROAD_CLIENT_ID) \
# --from-literal=gumroadClientSecret=$(GUMROAD_CLIENT_SECRET)
define _script
cat <<'EOF' | ctlptl apply -f -
apiVersion: ctlptl.dev/v1alpha1
kind: Cluster
product: minikube
registry: ctlptl-registry
kubernetesVersion: v1.28.3
EOF
endef
export script = $(value _script)
cluster:
@ eval "$$script"
minikube addons enable volumesnapshots
minikube addons enable csi-hostpath-driver
minikube addons enable metrics-server
# A gitea act runner which runs locally
# https://docs.gitea.com/next/usage/actions/overview
runner:
docker run -d --rm -e GITEA_INSTANCE_URL=https://gitea.futureporn.net -e GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_REGISTRATION_TOKEN} -v /var/run/docker.sock:/var/run/docker.sock --name fp-gitea-act-runner gitea/act_runner:latest

View File

@ -1,6 +1,25 @@
# futureporn-monorepo # futureporn-monorepo
## minikube setup ## development
minikube addons enable volumesnapshots [Tilt](https://docs.tilt.dev/) Handles auto-reloading dev containers when making changes to code.
minikube addons enable csi-hostpath-driver
### dependencies
docker
minikube
ctlptl
tilt
### setup
I would love for this to be a single command, `tilt up`, but minikube needs to get started and needs some addons.
@todo figure out a way to incorporate the minikube setup with `tilt up`
When enabling `csi-hostpath-driver`, it appears like it's locked up, but be sure to be patient and WAIT. It's just slow.
```
make cluster
```

View File

@ -10,10 +10,9 @@ docker_build('fp/link2cid', './packages/link2cid')
docker_build( docker_build(
'fp/strapi', 'fp/strapi',
'./packages/strapi', './packages/strapi',
dockerfile="prod.dockerfile" live_update=[
# live_update=[ sync('./packages/strapi', '/app')
# sync('./packages/strapi', '/app') ]
# ]
) )

View File

@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: helloworldy
labels:
app.kubernetes.io/name: helloworldy
spec:
containers:
- name: helloworldy
image: {{ .Values.helloworldy.containerName }}
ports:
- containerPort: 3000
resources: {}
livenessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 3
periodSeconds: 3
restartPolicy: OnFailure

View File

@ -0,0 +1,35 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ipfs-deployment
labels:
app: ipfs
app.kubernetes.io/name: ipfs
spec:
replicas: 1
selector:
matchLabels:
app: ipfs
template:
metadata:
labels:
app: ipfs
spec:
containers:
- name: ipfs
image: ipfs/kubo:release
livenessProbe:
httpGet:
path: /version
port: 5001
initialDelaySeconds: 3
periodSeconds: 3
resources:
limits:
cpu: 500m
memory: 512Mi
imagePullSecrets:
- name: regcred
ports:
- containerPort: 5001
- containerPort: 8080

View File

@ -1,26 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
annotations:
kompose.cmd: kompose convert --file compose.yml -c --out ./charts
kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels:
io.kompose.service: ipfs0
name: ipfs0
spec:
containers:
- image: ipfs/kubo:release
name: fp-ipfs0
ports:
- containerPort: 5001
resources: {}
volumeMounts:
- mountPath: /data/ipfs
name: ipfs0-claim0
restartPolicy: OnFailure
volumes:
- name: ipfs0-claim0
persistentVolumeClaim:
claimName: ipfs0-claim0
status: {}

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: loadbalancer
spec:
type: LoadBalancer
selector:
app: next-service
ports:
- protocol: TCP
port: 3000
targetPort: 3000
name: next-service

View File

@ -4,7 +4,6 @@ metadata:
annotations: annotations:
kompose.cmd: kompose convert --file compose.yml -c --out ./charts kompose.cmd: kompose convert --file compose.yml -c --out ./charts
kompose.version: 1.26.0 (40646f47) kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels: labels:
io.kompose.service: strapi io.kompose.service: strapi
name: strapi name: strapi
@ -52,7 +51,10 @@ spec:
name: fp-strapi name: fp-strapi
ports: ports:
- containerPort: 1337 - containerPort: 1337
resources: {} resources:
limits:
cpu: 500m
memory: 1Gi
volumeMounts: volumeMounts:
- mountPath: /opt/app - mountPath: /opt/app
name: strapi-claim0 name: strapi-claim0

View File

@ -0,0 +1,8 @@
apiVersion: kubelet.config.k8s.io/v1
kind: CredentialProviderConfig
providers:
- name: vultr-credential-provider
matchImages:
- "sjc.vultrcr.com/*"
defaultCacheDuration: "12h"
apiVersion: credentialprovider.kubelet.k8s.io/v1

View File

@ -0,0 +1,16 @@
# issuer-lets-encrypt-staging.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
preferredChain: "ISRG Root X1"
email: cj@futureporn.net
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
name: web-ingress

View File

@ -0,0 +1,23 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: next-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-staging
spec:
tls:
- secretName: next-tls
hosts:
- fp.sbtp.xyz
rules:
- host: fp.sbtp.xyz
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: next-service
port:
number: 80

View File

@ -0,0 +1,37 @@
apiVersion: v1
kind: Pod
metadata:
name: pgadmin-pod
labels:
app.kubernetes.io/name: pgadmin
spec:
containers:
- name: pgadmin
image: dpage/pgadmin4
ports:
- containerPort: 5050
resources:
limits:
cpu: 500m
memory: 1Gi
env:
- name: PGADMIN_LISTEN_PORT
value: '5050'
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres
key: password
- name: PGADMIN_DEFAULT_PASSWORD
valueFrom:
secretKeyRef:
name: pgadmin
key: defaultPassword
- name: PGADMIN_DEFAULT_EMAIL
valueFrom:
secretKeyRef:
name: pgadmin
key: defaultEmail
restartPolicy: OnFailure

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: pgadmin-service
spec:
selector:
app.kubernetes.io/name: pgadmin
ports:
- name: web
protocol: TCP
port: 5050
targetPort: 5050
status:
loadBalancer: {}

View File

@ -0,0 +1,27 @@
apiVersion: v1
kind: Pod
metadata:
name: postgres-pod
labels:
app.kubernetes.io/name: postgres
spec:
containers:
- name: postgres
image: postgres:16.0
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres
key: password
ports:
- containerPort: 5432
resources: {}
volumeMounts:
- name: postgres-pvc
mountPath: /data/postgres
restartPolicy: OnFailure
volumes:
- name: postgres-pvc
persistentVolumeClaim:
claimName: postgres-pvc

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 40Gi
allowVolumeExpansion: true
storageClassName: {{ .Values.storageClassName }}

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app.kubernetes.io/name: postgres
ports:
- name: db
protocol: TCP
port: 5432
targetPort: 5432
status:
loadBalancer: {}

View File

@ -0,0 +1,108 @@
apiVersion: v1
kind: Pod
metadata:
name: strapi-pod
spec:
containers:
- name: strapi-pod
image: {{ .Values.strapi.containerName }}
ports:
- containerPort: 1337
env:
- name: ADMIN_JWT_SECRET
valueFrom:
secretKeyRef:
name: strapi
key: ADMIN_JWT_SECRET
- name: API_TOKEN_SALT
valueFrom:
secretKeyRef:
name: strapi
key: API_TOKEN_SALT
- name: APP_KEYS
valueFrom:
secretKeyRef:
name: strapi
key: APP_KEYS
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: strapi
key: DATABASE_URL
- name: CDN_BUCKET_USC_URL
valueFrom:
secretKeyRef:
name: strapi
key: CDN_BUCKET_USC_URL
- name: DATABASE_CLIENT
value: postgres
- name: DATABASE_HOST
value: postgres-service
- name: DATABASE_NAME
value: futureporn-strapi
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: strapi
key: JWT_SECRET
- name: MUX_PLAYBACK_RESTRICTION_ID
valueFrom:
secretKeyRef:
name: strapi
key: MUX_PLAYBACK_RESTRICTION_ID
- name: MUX_SIGNING_KEY_ID
valueFrom:
secretKeyRef:
name: strapi
key: MUX_SIGNING_KEY_ID
- name: MUX_SIGNING_KEY_PRIVATE_KEY
valueFrom:
secretKeyRef:
name: strapi
key: MUX_SIGNING_KEY_PRIVATE_KEY
- name: NODE_ENV
value: production
- name: S3_USC_BUCKET_APPLICATION_KEY
valueFrom:
secretKeyRef:
name: strapi
key: S3_USC_BUCKET_APPLICATION_KEY
- name: S3_USC_BUCKET_ENDPOINT
valueFrom:
secretKeyRef:
name: strapi
key: S3_USC_BUCKET_ENDPOINT
- name: S3_USC_BUCKET_KEY_ID
valueFrom:
secretKeyRef:
name: strapi
key: S3_USC_BUCKET_KEY_ID
- name: S3_USC_BUCKET_NAME
valueFrom:
secretKeyRef:
name: strapi
key: S3_USC_BUCKET_NAME
- name: S3_USC_BUCKET_REGION
valueFrom:
secretKeyRef:
name: strapi
key: S3_USC_BUCKET_REGION
- name: SENDGRID_API_KEY
valueFrom:
secretKeyRef:
name: strapi
key: SENDGRID_API_KEY
- name: STRAPI_URL
value: {{ .Values.strapi.url }}
- name: TRANSFER_TOKEN_SALT
valueFrom:
secretKeyRef:
name: strapi
key: TRANSFER_TOKEN_SALT
- name: PORT
value: "{{ .Values.strapi.port }}"
resources:
limits:
cpu: 500m
memory: 1Gi
restartPolicy: OnFailure

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: strapi-service
spec:
selector:
app.kubernetes.io/name: strapi
ports:
- name: web
protocol: TCP
port: 1337
targetPort: 1337
status:
loadBalancer: {}

View File

@ -0,0 +1,23 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: cj@futureporn.net
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource that will be used to store the account's private key.
name: letsencrypt-staging
solvers:
- dns01:
webhook:
groupName: acme.vultr.com
solverName: vultr
config:
apiKeySecretRef:
key: apiKey
name: vultr-credentials

View File

@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/vultr-loadbalancer-protocol: "http"
service.beta.kubernetes.io/vultr-loadbalancer-https-ports: "443"
# You will need to have created a TLS Secret and pass in the name as the value
service.beta.kubernetes.io/vultr-loadbalancer-ssl: "ssl-secret"
name: vultr-lb-https
spec:
type: LoadBalancer
selector:
app: next-service
ports:
- port: 80
name: "http"
- port: 443
name: "https"

View File

@ -0,0 +1,22 @@
apiVersion: v1
kind: Pod
metadata:
name: ipfs-pod
labels:
app.kubernetes.io/name: ipfs
spec:
containers:
- name: ipfs
image: ipfs/kubo
ports:
- containerPort: 5001
- containerPort: 8080
resources: {}
volumeMounts:
- name: ipfs-pvc
mountPath: /data/ipfs
restartPolicy: OnFailure
volumes:
- name: ipfs-pvc
persistentVolumeClaim:
claimName: ipfs-pvc

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ipfs-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 40Gi
allowVolumeExpansion: true
storageClassName: {{ .Values.storageClassName }}

View File

@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: ipfs-service
spec:
selector:
app.kubernetes.io/name: ipfs
ports:
- name: gateway
protocol: TCP
port: 8080
targetPort: 8080
- name: api
protocol: TCP
port: 5001
targetPort: 5001
status:
loadBalancer: {}

View File

@ -5,10 +5,12 @@ metadata:
spec: spec:
containers: containers:
- name: link2cid-pod - name: link2cid-pod
image: fp/link2cid image: {{ .Values.link2cid.containerName }}
ports: ports:
- containerPort: 3939 - containerPort: 3939
env: env:
- name: IPFS_URL
value: http://ipfs-service:5001
- name: PORT - name: PORT
value: '3939' value: '3939'
- name: API_KEY - name: API_KEY
@ -20,4 +22,6 @@ spec:
limits: limits:
cpu: 500m cpu: 500m
memory: 1024Mi memory: 1024Mi
imagePullSecrets:
- name: regcred
restartPolicy: OnFailure restartPolicy: OnFailure

View File

@ -10,5 +10,3 @@ spec:
storage: 40Gi storage: 40Gi
allowVolumeExpansion: true allowVolumeExpansion: true
storageClassName: {{ .Values.storageClassName }} storageClassName: {{ .Values.storageClassName }}
status: {}

View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: next-pod
labels:
app.kubernetes.io/name: next
spec:
containers:
- name: next
image: {{ .Values.next.containerName }}
env:
- name: HOSTNAME
value: 0.0.0.0
ports:
- containerPort: 3000
resources: {}
restartPolicy: OnFailure

View File

@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: next-service
annotations:
service.beta.kubernetes.io/vultr-loadbalancer-protocol: "http"
service.beta.kubernetes.io/vultr-loadbalancer-algorithm: "least_connections"
spec:
type: LoadBalancer
selector:
name: next
ports:
- name: http
protocol: TCP
port: 3000
targetPort: 3000

View File

@ -1 +1,9 @@
storageClassName: csi-hostpath-sc storageClassName: csi-hostpath-sc
link2cid:
containerName: fp/link2cid
next:
containerName: fp/next
strapi:
containerName: fp/strapi
port: 1337
url: http://localhost:1337

View File

@ -0,0 +1,10 @@
storageClassName: vultr-block-storage-hdd
#storageClassName: civo-volume
link2cid:
containerName: gitea.futureporn.net/cj_clippy/link2cid:latest
next:
containerName: sjc.vultrcr.com/fpcontainers/next
strapi:
containerName: sjc.vultrcr.com/fpcontainers/strapi
port: 1337
url: https://portal.futureporn.net

View File

@ -1 +0,0 @@
storageClassName: vultr-block-storage-hdd

View File

@ -1,14 +1,20 @@
# repositories: repositories:
# - name: windmill - name: jetstack
# url: https://windmill-labs.github.io/windmill-helm-charts url: https://charts.jetstack.io
- name: vultr
url: https://vultr.github.io/helm-charts
releases: releases:
# - name: windmill
# namespace: windmill - name: cert-manager
# chart: windmill/windmill namespace: cert-manager
# values: chart: jetstack/cert-manager
# - ./charts/windmill/values.yaml
- name: fp - name: fp
namespace: default namespace: default
chart: charts/fp chart: charts/fp
values:
- charts/fp/values-prod.yaml

View File

@ -5,16 +5,9 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"kompose": "kompose convert --file compose.yml -c --out ./charts", "dev": "make cluster && tilt up"
"build:next": "docker build --build-arg=\"NEXT_PUBLIC_SITE_URL=https://futureporn.net\" --build-arg=\"NEXT_PUBLIC_STRAPI_URL=https://portal.futureporn.net\" --build-arg=\"NEXT_PUBLIC_UPPY_COMPANION_URL=https://uppy.futureporn.net\" -t fp-next:latest -f ./next.Dockerfile .",
"deploy:bot": "echo @todo",
"deploy:next": "git push origin:next main",
"deploy:link2cid": "echo @todo",
"deploy:strapi": "echo @todo",
"deploy:uppy": "echo @todo",
"deploy": "echo @todo"
}, },
"keywords": [], "keywords": [],
"author": "@cj_clippy", "author": "",
"license": "CC0-1.0" "license": "CC0-1.0"
} }

970
packages/bot/pnpm-lock.yaml Normal file
View File

@ -0,0 +1,970 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
'@types/express':
specifier: ^4.17.21
version: 4.17.21
'@types/node':
specifier: ^20.11.0
version: 20.11.29
discordeno:
specifier: ^18.0.1
version: 18.0.1
express:
specifier: ^4.18.2
version: 4.18.3
oceanic.js:
specifier: ^1.9.0
version: 1.9.0
devDependencies:
tsx:
specifier: ^4.7.0
version: 4.7.1
packages:
/@deno/shim-deno-test@0.3.3:
resolution: {integrity: sha512-Ge0Tnl7zZY0VvEfgsyLhjid8DzI1d0La0dgm+3m0/A8gZXgp5xwlyIyue5e4SCUuVB/3AH/0lun9LcJhhTwmbg==}
dev: false
/@deno/shim-deno@0.9.0:
resolution: {integrity: sha512-iP+qdI4Oy/Mw9yv40TqdjNKL+stpKDo8drki2cKisTXgZf+GoIdMhIuODxSypRyv6wxIuHNx7ZiKE3Sl3kAHuw==}
dependencies:
'@deno/shim-deno-test': 0.3.3
which: 2.0.2
dev: false
/@deno/shim-timers@0.1.0:
resolution: {integrity: sha512-XFRnB5Rtbkd5RiYHwhugNK9gvDgYXmFTUOT5dmhWCKG7WnOWZggbJMnH1NcyYS3QgHvmaTOaHCyNFNSv57j3Dg==}
dev: false
/@discordjs/voice@0.16.1:
resolution: {integrity: sha512-uiWiW0Ta6K473yf8zs13RfKuPqm/xU4m4dAidMkIdwqgy1CztbbZBtPLfDkVSKzpW7s6m072C+uQcs4LwF3FhA==}
engines: {node: '>=16.11.0'}
requiresBuild: true
dependencies:
'@types/ws': 8.5.10
discord-api-types: 0.37.61
prism-media: 1.3.5
tslib: 2.6.2
ws: 8.16.0
transitivePeerDependencies:
- '@discordjs/opus'
- bufferutil
- ffmpeg-static
- node-opus
- opusscript
- utf-8-validate
dev: false
optional: true
/@esbuild/aix-ppc64@0.19.12:
resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [aix]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm64@0.19.12:
resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm@0.19.12:
resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-x64@0.19.12:
resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-arm64@0.19.12:
resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-x64@0.19.12:
resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-arm64@0.19.12:
resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-x64@0.19.12:
resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm64@0.19.12:
resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm@0.19.12:
resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ia32@0.19.12:
resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-loong64@0.19.12:
resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-mips64el@0.19.12:
resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ppc64@0.19.12:
resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-riscv64@0.19.12:
resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-s390x@0.19.12:
resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-x64@0.19.12:
resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/netbsd-x64@0.19.12:
resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/openbsd-x64@0.19.12:
resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/sunos-x64@0.19.12:
resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-arm64@0.19.12:
resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-ia32@0.19.12:
resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-x64@0.19.12:
resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@fastify/busboy@2.1.1:
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'}
dev: false
/@types/body-parser@1.19.5:
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
dependencies:
'@types/connect': 3.4.38
'@types/node': 20.11.29
dev: false
/@types/connect@3.4.38:
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
dependencies:
'@types/node': 20.11.29
dev: false
/@types/express-serve-static-core@4.17.43:
resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==}
dependencies:
'@types/node': 20.11.29
'@types/qs': 6.9.13
'@types/range-parser': 1.2.7
'@types/send': 0.17.4
dev: false
/@types/express@4.17.21:
resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
dependencies:
'@types/body-parser': 1.19.5
'@types/express-serve-static-core': 4.17.43
'@types/qs': 6.9.13
'@types/serve-static': 1.15.5
dev: false
/@types/http-errors@2.0.4:
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
dev: false
/@types/mime@1.3.5:
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
dev: false
/@types/mime@3.0.4:
resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==}
dev: false
/@types/node@20.11.29:
resolution: {integrity: sha512-P99thMkD/1YkCvAtOd6/zGedKNA0p2fj4ZpjCzcNiSCBWgm3cNRTBfa/qjFnsKkkojxu4vVLtWpesnZ9+ap+gA==}
dependencies:
undici-types: 5.26.5
dev: false
/@types/qs@6.9.13:
resolution: {integrity: sha512-iLR+1vTTJ3p0QaOUq6ACbY1mzKTODFDT/XedZI8BksOotFmL4ForwDfRQ/DZeuTHR7/2i4lI1D203gdfxuqTlA==}
dev: false
/@types/range-parser@1.2.7:
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
dev: false
/@types/send@0.17.4:
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
dependencies:
'@types/mime': 1.3.5
'@types/node': 20.11.29
dev: false
/@types/serve-static@1.15.5:
resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==}
dependencies:
'@types/http-errors': 2.0.4
'@types/mime': 3.0.4
'@types/node': 20.11.29
dev: false
/@types/ws@8.5.10:
resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
requiresBuild: true
dependencies:
'@types/node': 20.11.29
dev: false
optional: true
/accepts@1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
dependencies:
mime-types: 2.1.35
negotiator: 0.6.3
dev: false
/array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
dev: false
/body-parser@1.20.2:
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dependencies:
bytes: 3.1.2
content-type: 1.0.5
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
http-errors: 2.0.0
iconv-lite: 0.4.24
on-finished: 2.4.1
qs: 6.11.0
raw-body: 2.5.2
type-is: 1.6.18
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
dev: false
/bytes@3.1.2:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
dev: false
/call-bind@1.0.7:
resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
engines: {node: '>= 0.4'}
dependencies:
es-define-property: 1.0.0
es-errors: 1.3.0
function-bind: 1.1.2
get-intrinsic: 1.2.4
set-function-length: 1.2.2
dev: false
/content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
dependencies:
safe-buffer: 5.2.1
dev: false
/content-type@1.0.5:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
dev: false
/cookie-signature@1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
dev: false
/cookie@0.5.0:
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
engines: {node: '>= 0.6'}
dev: false
/debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: false
/define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
dependencies:
es-define-property: 1.0.0
es-errors: 1.3.0
gopd: 1.0.1
dev: false
/depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
dev: false
/destroy@1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dev: false
/discord-api-types@0.37.61:
resolution: {integrity: sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw==}
requiresBuild: true
dev: false
optional: true
/discordeno@18.0.1:
resolution: {integrity: sha512-d3D/HpC39YGInmxy2HK90kPpMMu2gYYsWuwtEEFPWpq2hlR9dvad4ihvLursPz5bj4Ob1NWOgPv3kz/bwMSIpw==}
dependencies:
'@deno/shim-deno': 0.9.0
'@deno/shim-timers': 0.1.0
undici: 5.28.3
ws: 8.16.0
transitivePeerDependencies:
- bufferutil
- utf-8-validate
dev: false
/ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
dev: false
/encodeurl@1.0.2:
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
engines: {node: '>= 0.8'}
dev: false
/es-define-property@1.0.0:
resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
engines: {node: '>= 0.4'}
dependencies:
get-intrinsic: 1.2.4
dev: false
/es-errors@1.3.0:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
dev: false
/esbuild@0.19.12:
resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
optionalDependencies:
'@esbuild/aix-ppc64': 0.19.12
'@esbuild/android-arm': 0.19.12
'@esbuild/android-arm64': 0.19.12
'@esbuild/android-x64': 0.19.12
'@esbuild/darwin-arm64': 0.19.12
'@esbuild/darwin-x64': 0.19.12
'@esbuild/freebsd-arm64': 0.19.12
'@esbuild/freebsd-x64': 0.19.12
'@esbuild/linux-arm': 0.19.12
'@esbuild/linux-arm64': 0.19.12
'@esbuild/linux-ia32': 0.19.12
'@esbuild/linux-loong64': 0.19.12
'@esbuild/linux-mips64el': 0.19.12
'@esbuild/linux-ppc64': 0.19.12
'@esbuild/linux-riscv64': 0.19.12
'@esbuild/linux-s390x': 0.19.12
'@esbuild/linux-x64': 0.19.12
'@esbuild/netbsd-x64': 0.19.12
'@esbuild/openbsd-x64': 0.19.12
'@esbuild/sunos-x64': 0.19.12
'@esbuild/win32-arm64': 0.19.12
'@esbuild/win32-ia32': 0.19.12
'@esbuild/win32-x64': 0.19.12
dev: true
/escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
dev: false
/etag@1.8.1:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
dev: false
/express@4.18.3:
resolution: {integrity: sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==}
engines: {node: '>= 0.10.0'}
dependencies:
accepts: 1.3.8
array-flatten: 1.1.1
body-parser: 1.20.2
content-disposition: 0.5.4
content-type: 1.0.5
cookie: 0.5.0
cookie-signature: 1.0.6
debug: 2.6.9
depd: 2.0.0
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
finalhandler: 1.2.0
fresh: 0.5.2
http-errors: 2.0.0
merge-descriptors: 1.0.1
methods: 1.1.2
on-finished: 2.4.1
parseurl: 1.3.3
path-to-regexp: 0.1.7
proxy-addr: 2.0.7
qs: 6.11.0
range-parser: 1.2.1
safe-buffer: 5.2.1
send: 0.18.0
serve-static: 1.15.0
setprototypeof: 1.2.0
statuses: 2.0.1
type-is: 1.6.18
utils-merge: 1.0.1
vary: 1.1.2
transitivePeerDependencies:
- supports-color
dev: false
/finalhandler@1.2.0:
resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
engines: {node: '>= 0.8'}
dependencies:
debug: 2.6.9
encodeurl: 1.0.2
escape-html: 1.0.3
on-finished: 2.4.1
parseurl: 1.3.3
statuses: 2.0.1
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
dev: false
/forwarded@0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
dev: false
/fresh@0.5.2:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
dev: false
/fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
requiresBuild: true
dev: true
optional: true
/function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
dev: false
/get-intrinsic@1.2.4:
resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
engines: {node: '>= 0.4'}
dependencies:
es-errors: 1.3.0
function-bind: 1.1.2
has-proto: 1.0.3
has-symbols: 1.0.3
hasown: 2.0.2
dev: false
/get-tsconfig@4.7.3:
resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==}
dependencies:
resolve-pkg-maps: 1.0.0
dev: true
/gopd@1.0.1:
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
dependencies:
get-intrinsic: 1.2.4
dev: false
/has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
dependencies:
es-define-property: 1.0.0
dev: false
/has-proto@1.0.3:
resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
engines: {node: '>= 0.4'}
dev: false
/has-symbols@1.0.3:
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
engines: {node: '>= 0.4'}
dev: false
/hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
dependencies:
function-bind: 1.1.2
dev: false
/http-errors@2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
dependencies:
depd: 2.0.0
inherits: 2.0.4
setprototypeof: 1.2.0
statuses: 2.0.1
toidentifier: 1.0.1
dev: false
/iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
dependencies:
safer-buffer: 2.1.2
dev: false
/inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: false
/ipaddr.js@1.9.1:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'}
dev: false
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: false
/media-typer@0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
dev: false
/merge-descriptors@1.0.1:
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
dev: false
/methods@1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
dev: false
/mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
dev: false
/mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
dependencies:
mime-db: 1.52.0
dev: false
/mime@1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
hasBin: true
dev: false
/ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
dev: false
/ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
dev: false
/negotiator@0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
dev: false
/object-inspect@1.13.1:
resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
dev: false
/oceanic.js@1.9.0:
resolution: {integrity: sha512-zBHxBnJDkhYiHvQnTWcLsdRa/0v7+S2BYHWS3TLZpmMDXJU/+KOB9oL17YqSK8xvfpA0ykIsZTPKTgwxQUfLxA==}
engines: {node: '>=18.13.0'}
dependencies:
tslib: 2.6.2
ws: 8.16.0
optionalDependencies:
'@discordjs/voice': 0.16.1
transitivePeerDependencies:
- '@discordjs/opus'
- bufferutil
- ffmpeg-static
- node-opus
- opusscript
- utf-8-validate
dev: false
/on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
dependencies:
ee-first: 1.1.1
dev: false
/parseurl@1.3.3:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'}
dev: false
/path-to-regexp@0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
dev: false
/prism-media@1.3.5:
resolution: {integrity: sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==}
requiresBuild: true
peerDependencies:
'@discordjs/opus': '>=0.8.0 <1.0.0'
ffmpeg-static: ^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0
node-opus: ^0.3.3
opusscript: ^0.0.8
peerDependenciesMeta:
'@discordjs/opus':
optional: true
ffmpeg-static:
optional: true
node-opus:
optional: true
opusscript:
optional: true
dev: false
optional: true
/proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
dependencies:
forwarded: 0.2.0
ipaddr.js: 1.9.1
dev: false
/qs@6.11.0:
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
engines: {node: '>=0.6'}
dependencies:
side-channel: 1.0.6
dev: false
/range-parser@1.2.1:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
dev: false
/raw-body@2.5.2:
resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
engines: {node: '>= 0.8'}
dependencies:
bytes: 3.1.2
http-errors: 2.0.0
iconv-lite: 0.4.24
unpipe: 1.0.0
dev: false
/resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
dev: true
/safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: false
/safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
dev: false
/send@0.18.0:
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
engines: {node: '>= 0.8.0'}
dependencies:
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
fresh: 0.5.2
http-errors: 2.0.0
mime: 1.6.0
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
statuses: 2.0.1
transitivePeerDependencies:
- supports-color
dev: false
/serve-static@1.15.0:
resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
engines: {node: '>= 0.8.0'}
dependencies:
encodeurl: 1.0.2
escape-html: 1.0.3
parseurl: 1.3.3
send: 0.18.0
transitivePeerDependencies:
- supports-color
dev: false
/set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
dependencies:
define-data-property: 1.1.4
es-errors: 1.3.0
function-bind: 1.1.2
get-intrinsic: 1.2.4
gopd: 1.0.1
has-property-descriptors: 1.0.2
dev: false
/setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
dev: false
/side-channel@1.0.6:
resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
es-errors: 1.3.0
get-intrinsic: 1.2.4
object-inspect: 1.13.1
dev: false
/statuses@2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
dev: false
/toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
dev: false
/tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
dev: false
/tsx@4.7.1:
resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==}
engines: {node: '>=18.0.0'}
hasBin: true
dependencies:
esbuild: 0.19.12
get-tsconfig: 4.7.3
optionalDependencies:
fsevents: 2.3.3
dev: true
/type-is@1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'}
dependencies:
media-typer: 0.3.0
mime-types: 2.1.35
dev: false
/undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
dev: false
/undici@5.28.3:
resolution: {integrity: sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==}
engines: {node: '>=14.0'}
dependencies:
'@fastify/busboy': 2.1.1
dev: false
/unpipe@1.0.0:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
dev: false
/utils-merge@1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'}
dev: false
/vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
dev: false
/which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
hasBin: true
dependencies:
isexe: 2.0.0
dev: false
/ws@8.16.0:
resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
dev: false

View File

@ -0,0 +1,20 @@
# Base Image
FROM golang:latest
# Set the Current Working Directory inside the container
WORKDIR /app
# Copy everything from the current directory to the PWD(Present Working Directory) inside the container
COPY . .
# Download all the dependencies
RUN go mod download
# Build the Go app
RUN go build -o main .
# Expose port 8080 to the outside world
EXPOSE 8080
# Command to run the executable
CMD ["./main"]

View File

View File

@ -0,0 +1,13 @@
package main
import "net/http"
func main() {
http.HandleFunc("/", hellowordhandler)
http.ListenAndServe(":9000", nil)
}
func hellowordhandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
}

View File

@ -0,0 +1,2 @@
node_modules
README.md

36
packages/helloworldy/.gitignore vendored Normal file
View File

@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@ -0,0 +1,12 @@
FROM node:20
RUN corepack enable
WORKDIR /app
ADD package.json .
ADD package-lock.json .
RUN pnpm install
ADD . .
ENTRYPOINT [ "pnpm", "next", "dev" ]

View File

@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,107 @@
:root {
--max-width: 1100px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
"Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
"Fira Mono", "Droid Sans Mono", "Courier New", monospace;
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
--primary-glow: conic-gradient(
from 180deg at 50% 50%,
#16abff33 0deg,
#0885ff33 55deg,
#54d6ff33 120deg,
#0071ff33 160deg,
transparent 360deg
);
--secondary-glow: radial-gradient(
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
);
--tile-start-rgb: 239, 245, 249;
--tile-end-rgb: 228, 232, 233;
--tile-border: conic-gradient(
#00000080,
#00000040,
#00000030,
#00000020,
#00000010,
#00000010,
#00000080
);
--callout-rgb: 238, 240, 241;
--callout-border-rgb: 172, 175, 176;
--card-rgb: 180, 185, 188;
--card-border-rgb: 131, 134, 135;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
--secondary-glow: linear-gradient(
to bottom right,
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0.3)
);
--tile-start-rgb: 2, 13, 46;
--tile-end-rgb: 2, 5, 19;
--tile-border: conic-gradient(
#ffffff80,
#ffffff40,
#ffffff30,
#ffffff20,
#ffffff10,
#ffffff10,
#ffffff80
);
--callout-rgb: 20, 20, 20;
--callout-border-rgb: 108, 108, 108;
--card-rgb: 100, 100, 100;
--card-border-rgb: 200, 200, 200;
}
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}
a {
color: inherit;
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}

View File

@ -0,0 +1,17 @@
import { Inter } from "next/font/google";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}

View File

@ -0,0 +1,95 @@
import Image from "next/image";
import styles from "./page.module.css";
export default function Home() {
return (
<main className={styles.main}>
<div className={styles.description}>
<p>
Get started by editing&nbsp;
<code className={styles.code}>app/page.js</code>
</p>
<div>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
By{" "}
<Image
src="/vercel.svg"
alt="Vercel Logo"
className={styles.vercelLogo}
width={100}
height={24}
priority
/>
</a>
</div>
</div>
<div className={styles.center}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
</div>
<div className={styles.grid}>
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Docs <span>-&gt;</span>
</h2>
<p>Find in-depth information about Next.js features and API.</p>
</a>
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Learn <span>-&gt;</span>
</h2>
<p>Learn about Next.js in an interactive course with&nbsp;quizzes!</p>
</a>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Templates <span>-&gt;</span>
</h2>
<p>Explore starter templates for Next.js.</p>
</a>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Deploy <span>-&gt;</span>
</h2>
<p>
Instantly deploy your Next.js site to a shareable URL with Vercel.
</p>
</a>
</div>
</main>
);
}

View File

@ -0,0 +1,230 @@
.main {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 6rem;
min-height: 100vh;
}
.description {
display: inherit;
justify-content: inherit;
align-items: inherit;
font-size: 0.85rem;
max-width: var(--max-width);
width: 100%;
z-index: 2;
font-family: var(--font-mono);
}
.description a {
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
}
.description p {
position: relative;
margin: 0;
padding: 1rem;
background-color: rgba(var(--callout-rgb), 0.5);
border: 1px solid rgba(var(--callout-border-rgb), 0.3);
border-radius: var(--border-radius);
}
.code {
font-weight: 700;
font-family: var(--font-mono);
}
.grid {
display: grid;
grid-template-columns: repeat(4, minmax(25%, auto));
max-width: 100%;
width: var(--max-width);
}
.card {
padding: 1rem 1.2rem;
border-radius: var(--border-radius);
background: rgba(var(--card-rgb), 0);
border: 1px solid rgba(var(--card-border-rgb), 0);
transition: background 200ms, border 200ms;
}
.card span {
display: inline-block;
transition: transform 200ms;
}
.card h2 {
font-weight: 600;
margin-bottom: 0.7rem;
}
.card p {
margin: 0;
opacity: 0.6;
font-size: 0.9rem;
line-height: 1.5;
max-width: 30ch;
text-wrap: balance;
}
.center {
display: flex;
justify-content: center;
align-items: center;
position: relative;
padding: 4rem 0;
}
.center::before {
background: var(--secondary-glow);
border-radius: 50%;
width: 480px;
height: 360px;
margin-left: -400px;
}
.center::after {
background: var(--primary-glow);
width: 240px;
height: 180px;
z-index: -1;
}
.center::before,
.center::after {
content: "";
left: 50%;
position: absolute;
filter: blur(45px);
transform: translateZ(0);
}
.logo {
position: relative;
}
/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
.card:hover {
background: rgba(var(--card-rgb), 0.1);
border: 1px solid rgba(var(--card-border-rgb), 0.15);
}
.card:hover span {
transform: translateX(4px);
}
}
@media (prefers-reduced-motion) {
.card:hover span {
transform: none;
}
}
/* Mobile */
@media (max-width: 700px) {
.content {
padding: 4rem;
}
.grid {
grid-template-columns: 1fr;
margin-bottom: 120px;
max-width: 320px;
text-align: center;
}
.card {
padding: 1rem 2.5rem;
}
.card h2 {
margin-bottom: 0.5rem;
}
.center {
padding: 8rem 0 6rem;
}
.center::before {
transform: none;
height: 300px;
}
.description {
font-size: 0.8rem;
}
.description a {
padding: 1rem;
}
.description p,
.description div {
display: flex;
justify-content: center;
position: fixed;
width: 100%;
}
.description p {
align-items: center;
inset: 0 0 auto;
padding: 2rem 1rem 1.4rem;
border-radius: 0;
border: none;
border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
background: linear-gradient(
to bottom,
rgba(var(--background-start-rgb), 1),
rgba(var(--callout-rgb), 0.5)
);
background-clip: padding-box;
backdrop-filter: blur(24px);
}
.description div {
align-items: flex-end;
pointer-events: none;
inset: auto 0 0;
padding: 2rem;
height: 200px;
background: linear-gradient(
to bottom,
transparent 0%,
rgb(var(--background-end-rgb)) 40%
);
z-index: 1;
}
}
/* Tablet and Smaller Desktop */
@media (min-width: 701px) and (max-width: 1120px) {
.grid {
grid-template-columns: repeat(2, 50%);
}
}
@media (prefers-color-scheme: dark) {
.vercelLogo {
filter: invert(1);
}
.logo {
filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
}
}
@keyframes rotate {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}

View File

@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}

View File

@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;

389
packages/helloworldy/package-lock.json generated Normal file
View File

@ -0,0 +1,389 @@
{
"name": "helloworldy",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "helloworldy",
"version": "0.1.0",
"dependencies": {
"next": "14.1.3",
"react": "^18",
"react-dom": "^18"
}
},
"node_modules/@next/env": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.3.tgz",
"integrity": "sha512-VhgXTvrgeBRxNPjyfBsDIMvgsKDxjlpw4IAUsHCX8Gjl1vtHUYRT3+xfQ/wwvLPDd/6kqfLqk9Pt4+7gysuCKQ=="
},
"node_modules/@next/swc-darwin-arm64": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.3.tgz",
"integrity": "sha512-LALu0yIBPRiG9ANrD5ncB3pjpO0Gli9ZLhxdOu6ZUNf3x1r3ea1rd9Q+4xxUkGrUXLqKVK9/lDkpYIJaCJ6AHQ==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.3.tgz",
"integrity": "sha512-E/9WQeXxkqw2dfcn5UcjApFgUq73jqNKaE5bysDm58hEUdUGedVrnRhblhJM7HbCZNhtVl0j+6TXsK0PuzXTCg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.3.tgz",
"integrity": "sha512-USArX9B+3rZSXYLFvgy0NVWQgqh6LHWDmMt38O4lmiJNQcwazeI6xRvSsliDLKt+78KChVacNiwvOMbl6g6BBw==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.3.tgz",
"integrity": "sha512-esk1RkRBLSIEp1qaQXv1+s6ZdYzuVCnDAZySpa62iFTMGTisCyNQmqyCTL9P+cLJ4N9FKCI3ojtSfsyPHJDQNw==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.3.tgz",
"integrity": "sha512-8uOgRlYEYiKo0L8YGeS+3TudHVDWDjPVDUcST+z+dUzgBbTEwSSIaSgF/vkcC1T/iwl4QX9iuUyUdQEl0Kxalg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.3.tgz",
"integrity": "sha512-DX2zqz05ziElLoxskgHasaJBREC5Y9TJcbR2LYqu4r7naff25B4iXkfXWfcp69uD75/0URmmoSgT8JclJtrBoQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.3.tgz",
"integrity": "sha512-HjssFsCdsD4GHstXSQxsi2l70F/5FsRTRQp8xNgmQs15SxUfUJRvSI9qKny/jLkY3gLgiCR3+6A7wzzK0DBlfA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.3.tgz",
"integrity": "sha512-DRuxD5axfDM1/Ue4VahwSxl1O5rn61hX8/sF0HY8y0iCbpqdxw3rB3QasdHn/LJ6Wb2y5DoWzXcz3L1Cr+Thrw==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.3.tgz",
"integrity": "sha512-uC2DaDoWH7h1P/aJ4Fok3Xiw6P0Lo4ez7NbowW2VGNXw/Xv6tOuLUcxhBYZxsSUJtpeknCi8/fvnSpyCFp4Rcg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@swc/helpers": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
"integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dependencies": {
"streamsearch": "^1.1.0"
},
"engines": {
"node": ">=10.16.0"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001599",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz",
"integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
]
},
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/next": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/next/-/next-14.1.3.tgz",
"integrity": "sha512-oexgMV2MapI0UIWiXKkixF8J8ORxpy64OuJ/J9oVUmIthXOUCcuVEZX+dtpgq7wIfIqtBwQsKEDXejcjTsan9g==",
"dependencies": {
"@next/env": "14.1.3",
"@swc/helpers": "0.5.2",
"busboy": "1.6.0",
"caniuse-lite": "^1.0.30001579",
"graceful-fs": "^4.2.11",
"postcss": "8.4.31",
"styled-jsx": "5.1.1"
},
"bin": {
"next": "dist/bin/next"
},
"engines": {
"node": ">=18.17.0"
},
"optionalDependencies": {
"@next/swc-darwin-arm64": "14.1.3",
"@next/swc-darwin-x64": "14.1.3",
"@next/swc-linux-arm64-gnu": "14.1.3",
"@next/swc-linux-arm64-musl": "14.1.3",
"@next/swc-linux-x64-gnu": "14.1.3",
"@next/swc-linux-x64-musl": "14.1.3",
"@next/swc-win32-arm64-msvc": "14.1.3",
"@next/swc-win32-ia32-msvc": "14.1.3",
"@next/swc-win32-x64-msvc": "14.1.3"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"sass": "^1.3.0"
},
"peerDependenciesMeta": {
"@opentelemetry/api": {
"optional": true
},
"sass": {
"optional": true
}
}
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
},
"peerDependencies": {
"react": "^18.2.0"
}
},
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"dependencies": {
"loose-envify": "^1.1.0"
}
},
"node_modules/source-map-js": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.1.0.tgz",
"integrity": "sha512-9vC2SfsJzlej6MAaMPLu8HiBSHGdRAJ9hVFYN1ibZoNkeanmDmLUcIrj6G9DGL7XMJ54AKg/G75akXl1/izTOw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/styled-jsx": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
"integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
"dependencies": {
"client-only": "0.0.1"
},
"engines": {
"node": ">= 12.0.0"
},
"peerDependencies": {
"react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
},
"peerDependenciesMeta": {
"@babel/core": {
"optional": true
},
"babel-plugin-macros": {
"optional": true
}
}
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
}
}
}

View File

@ -0,0 +1,16 @@
{
"name": "helloworldy",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"react": "^18",
"react-dom": "^18",
"next": "14.1.3"
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>

After

Width:  |  Height:  |  Size: 629 B

View File

@ -0,0 +1,3 @@
PORT=3030
IPFS_URL=http://localhost:5001
API_KEY=changeme

View File

@ -27,6 +27,21 @@ const ipfsUrl = process.env.IPFS_URL || 'http://localhost:5001';
if (!process.env.API_KEY) throw new Error('API_KEY was missing in env'); if (!process.env.API_KEY) throw new Error('API_KEY was missing in env');
if (!process.env.PORT) throw new Error('PORT is missing in env'); if (!process.env.PORT) throw new Error('PORT is missing in env');
async function ipfsHealthCheck() {
const url = ipfsUrl+'/version'
// console.log(`ipfsHealthCheck at url=${url}`)
try {
const res = await fetch(url, {
method: 'GET'
})
const body = await res.text()
if (!body.includes('Version')) throw new Error('response from ipfs did not contain Version')
} catch (e) {
console.error('failure while checking IPFS connection.')
console.error(e)
}
}
// greetz https://stackoverflow.com/a/51302466/1004931 // greetz https://stackoverflow.com/a/51302466/1004931
async function downloadFile(url, filePath, sse) { async function downloadFile(url, filePath, sse) {
console.log(`downloading url=${url} to filePath=${filePath}`); console.log(`downloading url=${url} to filePath=${filePath}`);
@ -69,7 +84,6 @@ async function downloadFile(url, filePath, sse) {
// If we don't, we get text error messages sent to kubo which gets added and it's a bad time. // If we don't, we get text error messages sent to kubo which gets added and it's a bad time.
console.log(`fileSize=${fileSize}. downloadedBytes=${downloadedBytes}`); console.log(`fileSize=${fileSize}. downloadedBytes=${downloadedBytes}`);
if (fileSize != downloadedBytes) throw new Error('downloadedBytes did not match fileSize'); if (fileSize != downloadedBytes) throw new Error('downloadedBytes did not match fileSize');
} }
@ -279,6 +293,9 @@ app.get('/health', healthRes);
app.get('/add', authenticate, addHandler); app.get('/add', authenticate, addHandler);
app.listen(port, async () => { app.listen(port, async () => {
setInterval(async () => {
await ipfsHealthCheck()
}, 10000)
const version = await getPackageVersion(); const version = await getPackageVersion();
console.log(`link2cid ${version} listening on port ${port}`); console.log(`link2cid ${version} listening on port ${port}`);
}); });

View File

@ -9,24 +9,26 @@ export default async function Page() {
return ( return (
<> <>
<div className="content"> <div className="content">
<div className="box">
<div className="block">
<h1>About</h1> <section className="hero">
<div className="section hero is-primary"> <div className="hero-body">
<p className="title">About</p>
<p>Futureporn is a fanmade public archive of NSFW R18 vtuber livestreams.</p> <p>Futureporn is a fanmade public archive of NSFW R18 vtuber livestreams.</p>
</div> </div>
</section>
<div className="section">
<h1>Mission</h1> <h1>Mission</h1>
<div className="section">
<p>It&apos;s a lofty goal, but Futureporn aims to become <b>the Galaxy&apos;s best VTuber hentai site.</b></p> <p>It&apos;s a lofty goal, but Futureporn aims to become <b>the Galaxy&apos;s best VTuber hentai site.</b></p>
</div> </div>
<div className="section">
<h2>How do we get there?</h2> <h2>How do we get there?</h2>
<div className="section">
<h3>1. Solve the viewer&apos;s common problems</h3> <h3>1. Solve the viewer&apos;s common problems</h3>
<p>Viewers want to watch livestream VODs on their own time. Futureporn collects vods from public streams, and caches them for later viewing.</p> <p>Viewers want to watch livestream VODs on their own time. Futureporn collects vods from public streams, and caches them for later viewing.</p>
@ -49,16 +51,15 @@ export default async function Page() {
</div> </div>
<div className="section"> <div className="section">
<article className="mt-5 message is-success"> <article className="mt-5 message is-success">
<div className="message-body"> <div className="message-body">
<p>Futureporn needs financial support to continue improving. If you enjoy this website, please consider <Link target="_blank" href="https://patreon.com/CJ_Clippy">becoming a patron<FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></Link>.</p> <p>Futureporn needs financial support to continue improving. If you enjoy this website, please consider <Link target="_blank" href="https://patreon.com/CJ_Clippy">becoming a patron<FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt ml-1" /></Link>.</p>
</div> </div>
</article> </article>
</div> </div>
</div> </div>
</div>
</div>
</> </>
) )
} }

View File

@ -1,80 +0,0 @@
import React, { useEffect, useRef, useState, forwardRef, MutableRefObject } from "react";
import { APITypes, PlyrProps, usePlyr } from "plyr-react";
import "plyr-react/plyr.css";
import { Options } from "plyr";
import Hls from "hls.js";
export function UnsupportedHlsMessage(): React.JSX.Element {
return (
<div className="unsupported-hls">
HLS is not supported in your browser. Please try a different browser.
</div>
);
}
const useHls = (src: string, options: Options | null) => {
const hls = useRef<Hls>(new Hls());
const hasQuality = useRef<boolean>(false);
const [plyrOptions, setPlyrOptions] = useState<Options | null>(options);
useEffect(() => {
hasQuality.current = false;
}, [options]);
useEffect(() => {
hls.current.loadSource(src);
hls.current.attachMedia(document.querySelector(".plyr-react")!);
hls.current.on(Hls.Events.MANIFEST_PARSED, () => {
if (hasQuality.current) return; // early quit if already set
const levels = hls.current.levels;
const quality: Options["quality"] = {
default: levels[levels.length - 1].height,
options: levels.map((level) => level.height),
forced: true,
onChange: (newQuality: number) => {
levels.forEach((level, levelIndex) => {
if (level.height === newQuality) {
hls.current.currentLevel = levelIndex;
}
});
},
};
setPlyrOptions({ ...plyrOptions, quality });
hasQuality.current = true;
});
});
return { options: plyrOptions };
};
const CustomPlyrInstance = forwardRef<
APITypes,
PlyrProps & { hlsSource: string; mainColor: string; plyrOptions: Options }
>((props, ref) => {
const { source, plyrOptions, hlsSource, mainColor } = props;
const plyrRef = usePlyr(ref, {
...useHls(hlsSource, plyrOptions),
source,
}) as MutableRefObject<HTMLVideoElement>;
return (
<>
<video
ref={plyrRef}
className="plyr-react plyr"
style={{ "--plyr-color-main": mainColor } as React.CSSProperties}
></video>
</>
);
});
CustomPlyrInstance.displayName = 'CustomPlyrInstance'
export { CustomPlyrInstance }

View File

@ -30,8 +30,10 @@ export default async function FundingGoal(): Promise<React.JSX.Element> {
{JSON.stringify(goals, null, 2)} {JSON.stringify(goals, null, 2)}
</code> </code>
</pre> */} </pre> */}
<div className="section">
<article className="message is-info">
<article className="message">
<div className="message-header"> <div className="message-header">
Funding Goal Funding Goal
<figure className="image is-32x32 is-rounded"> <figure className="image is-32x32 is-rounded">
@ -50,7 +52,7 @@ export default async function FundingGoal(): Promise<React.JSX.Element> {
<p className="subtitle">${(goals.featuredFunded.amountCents * (goals.featuredFunded.completedPercentage * 0.01) / 100)} of {goals.featuredFunded.amountCents / 100} ({goals.featuredFunded.completedPercentage}%) <p className="subtitle">${(goals.featuredFunded.amountCents * (goals.featuredFunded.completedPercentage * 0.01) / 100)} of {goals.featuredFunded.amountCents / 100} ({goals.featuredFunded.completedPercentage}%)
</p> </p>
<div className="mb-5 tag is-success is-rounded" style={{ width: '100%' }}> <div className="mb-5 tag is-success has-text-white is-rounded" style={{ width: '100%' }}>
FUNDED FUNDED
</div> </div>
<p>{goals.featuredFunded.description}</p> <p>{goals.featuredFunded.description}</p>
@ -75,6 +77,7 @@ export default async function FundingGoal(): Promise<React.JSX.Element> {
</p> </p>
</div> </div>
</article> </article>
</div>
</> </>
); );
}; };

View File

@ -11,7 +11,6 @@ export default function Pager({ baseUrl, page, pageCount }: IPagerProps): React.
const getPagePath = (page: any): string => { const getPagePath = (page: any): string => {
const pageNumber = parseInt(page); const pageNumber = parseInt(page);
console.log(`pageNumber=${pageNumber}`);
return `${baseUrl}/${pageNumber}`; return `${baseUrl}/${pageNumber}`;
}; };

View File

@ -5,8 +5,6 @@ import { faCalendar } from "@fortawesome/free-solid-svg-icons";
export function StreamButton({ stream }: { stream: IStream }) { export function StreamButton({ stream }: { stream: IStream }) {
if (!stream) return <></> if (!stream) return <></>
// return <p>{JSON.stringify(stream, null, 2)}</p>
// return <span className="button is-small">{new Date(stream.attributes.date).toLocaleDateString()}</span>
return ( return (
<Link <Link

View File

@ -1,7 +1,7 @@
'use client'; 'use client';
import { IStream } from "@/lib/streams"; import { IStream } from "@/lib/streams";
import NotFound from "app/streams/[cuid]/not-found"; // import NotFound from "app/streams/[cuid]/not-found";
import { IVod } from "@/lib/vods"; import { IVod } from "@/lib/vods";
import Link from "next/link"; import Link from "next/link";
import Image from "next/image"; import Image from "next/image";
@ -77,7 +77,8 @@ export default function StreamPage({ stream }: IStreamProps) {
setHemisphere(randomHemisphere); setHemisphere(randomHemisphere);
}, []); }, []);
if (!stream) return <NotFound></NotFound> if (!stream) return <p>NotFound</p>
// <NotFound></NotFound>
// return <p> // return <p>
// <pre> // <pre>

View File

@ -1,83 +0,0 @@
'use client';
import FullCalendar from "@fullcalendar/react";
import interactionPlugin, { DateClickArg } from '@fullcalendar/interaction';
import dayGridPlugin from '@fullcalendar/daygrid';
import multiMonthPlugin from '@fullcalendar/multimonth'
import { IStream } from "@/lib/streams";
import { useRouter } from 'next/navigation';
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
interface IStreamsCalendarProps {
missingStreams: IStream[];
issueStreams: IStream[];
goodStreams: IStream[];
}
interface IEvent {
cuid: string;
start: Date;
end?: Date;
title: string;
vtuber: string;
}
// function buildStreamPageUrlFromDate(date: Date) {
// // const cuid =
// return `/s/${safeDate}`;
// }
function handleEventClick(info: any, router: AppRouterInstance) {
var eventObj = info.event;
const { cuid } = eventObj._def.extendedProps;
router.push(`/streams/${cuid}`);
}
function convertStreamToEvent(stream: IStream): IEvent {
console.log(stream)
const displayName = stream.attributes.vtuber.data.attributes.displayName;
return {
cuid: stream.attributes.cuid,
start: new Date(stream.attributes.date),
title: `${displayName}`,
vtuber: displayName
}
}
export default function StreamsCalendar({ missingStreams, issueStreams, goodStreams }: IStreamsCalendarProps) {
const router = useRouter();
const eventSources = [
{
events: missingStreams.map(convertStreamToEvent),
color: 'red'
},
{
events: issueStreams.map(convertStreamToEvent),
color: 'yellow',
},
{
events: goodStreams.map(convertStreamToEvent),
color: 'green'
}
]
return (
<>
<FullCalendar
plugins={[
dayGridPlugin,
interactionPlugin
]}
editable={false}
eventSources={eventSources}
eventClick={(args) => {
handleEventClick(args, router);
}}
/>
</>
)
}

View File

@ -0,0 +1,24 @@
'use client'
import LinkableHeading from "./linkable-heading"
import Image from "next/image"
import { useState } from "react"
import styles from '@/assets/styles/fp.module.css'
export default function Thumbnail({url}: { url: string }) {
const [isBig, setIsBig] = useState(false)
return (
<div>
<Image
className={(isBig) ? styles.zoomout : styles.zoomin}
onClick={() => setIsBig(!isBig)}
src={url}
alt="A composite image showing several frames from the source video"
width={(isBig) ? 1920 : 192}
height={(isBig) ? 1080 : 108}
quality={(isBig) ? 100 : 75}
></Image>
</div>
)
}

View File

@ -163,219 +163,231 @@ export default function UploadForm({ vtubers }: IUploadFormProps) {
setValue('files', files); setValue('files', files);
}); });
return (
<>
<div className='section'> return (<div className="notification is-secondary">
<h2 className='title is-2'>Upload VOD</h2> <h1 className="title">VOD uploads</h1>
<p className="mb-5"><i>Together we can archive all lewdtuber livestreams!</i></p>
{(!authData?.accessToken)
?
<>
<aside className='notification is-danger'><p>Please log in to upload VODs</p></aside>
<LoginButton />
</>
: (
<div className='columns is-multiline'>
<form id="vod-details" onSubmit={handleSubmit(createUSC)}>
{(!isSubmitSuccessful) && <div className='column is-full'>
<section className="hero is-info mb-3">
<div className="hero-body">
<p className="title">
Step 1
</p>
<p className="subtitle">
Upload the file
</p>
</div>
</section>
<section className="section mb-5">
<Dashboard
uppy={uppy}
theme='dark'
proudlyDisplayPoweredByUppy={false}
/>
<input
required
hidden={true}
style={{ display: 'none' }}
className="input" type="text"
{...register('files')}
></input>
{errors.files && <p className="help is-danger">{errors.files.message?.toString()}</p>}
</section>
</div>}
{(!isSubmitSuccessful) && <div className='column is-full '>
{/* {(!cuid) && <aside className='notification is-info'>Hint: Some of these fields are filled out automatically when uploading from a <Link href="/streams">stream</Link> page.</aside>} */}
<section className="hero is-info mb-3">
<div className="hero-body">
<p className="title">
Step 2
</p>
<p className="subtitle">
Tell us about the VOD
</p>
</div>
</section>
<section className="section">
{/* <input
required
// hidden={false}
// style={{ display: 'none' }}
className="input" type="text"
{...register('streamCuid')}
></input> */}
<div className="field">
<label className="label">VTuber</label>
<div className="select">
<select
required
// value={vtuber}
// onChange={(evt) => setVtuber(parseInt(evt.target.value))}
{...register('vtuber')}
>
{vtubers.map((vtuber: IVtuber) => (
<option key={vtuber.id} value={vtuber.id}>{vtuber.attributes.displayName}</option>
))}
</select>
</div>
<p className="help is-info">Choose the VTuber this VOD belongs to. (More VTubers will be added when storage/bandwidth funding is secured.)</p>
{errors.vtuber && <p className="help is-danger">vtuber error</p>}
</div>
<div className="field">
<label className="label">Stream Date</label>
<input
required
className="input" type="date"
{...register('date')}
// onChange={(evt) => setDate(evt.target.value)}
></input>
<p className="help is-info">The date when the VOD was originally streamed.</p>
{errors.date && <p className="help is-danger">{errors.date.message?.toString()}</p>}
</div>
<div className="field">
<label className="label">Notes</label>
<textarea
className="textarea"
placeholder="e.g. Missing first 10 minutes of stream"
// onChange={(evt) => setNote(evt.target.value)}
{...register('notes')}
></textarea>
<p className="help is-info">If there are any issues with the VOD, put a note here. If there are no VOD issues, leave this field blank.</p>
</div>
<div className="field">
<label className="label">Attribution</label>
<label className="checkbox">
<input
type="checkbox"
// onChange={(evt) => setAttribution(evt.target.checked)}
{...register('attribution')}
/>
<span className={`ml-2 ${styles.noselect}`}>Credit {authData.user?.username} for the upload.</span>
<p className="help is-info">Check this box if you want your username displayed on the website. Thank you for uploading!</p>
</label>
</div>
</section>
</div>}
<div className="column is-full">
<section className="hero is-info">
<div className="hero-body">
<p className="title">
Step 3
</p>
<p className="subtitle">
Send the form
</p>
</div>
</section>
<section className="section">
{errors.root?.serverError && (
<div className="notification">
<button className="delete" onClick={() => clearErrors()}></button>
<ErrorMessage name="root" errors={errors} ></ErrorMessage>
</div>
)}
{!isSubmitSuccessful && (
<button className="button is-primary is-large mt-5">
<span className="icon is-small">
<FontAwesomeIcon icon={faPaperPlane}></FontAwesomeIcon>
</span>
<span>Send</span>
</button>
)}
{isSubmitting && (
<p> <p>
<FontAwesomeIcon className="mt-5 fa-spin-pulse" icon={faSpinner} ></FontAwesomeIcon> <i>coming soon!!</i>
</p> </p>
)} <hr ></hr>
{isSubmitSuccessful && ( <p>Track progress on the <a href="/goals">Goals Page</a></p>
<> </div>)
<aside className="notification mt-5 is-success">Thank you for uploading! </aside>
<button onClick={() => {
reset(); // reset form // return (
const files = uppy.getFiles() // <>
for (const file of files) {
uppy.removeFile(file.id); // reset uppy // <div className='section'>
} // <h2 className='title is-2'>Upload VOD</h2>
}} className="button is-primary">
<span className="icon is-small"> // <p className="mb-5"><i>Together we can archive all lewdtuber livestreams!</i></p>
<FontAwesomeIcon icon={faEraser}></FontAwesomeIcon>
</span> // {(!authData?.accessToken)
<span>Reset form</span> // ?
</button> // <>
</> // <aside className='notification is-danger'><p>Please log in to upload VODs</p></aside>
)} // <LoginButton />
// </>
// : (
</section> // <div className='columns is-multiline'>
</div> // <form id="vod-details" onSubmit={handleSubmit(createUSC)}>
</form>
</div>
) // {(!isSubmitSuccessful) && <div className='column is-full'>
} // <section className="hero is-info mb-3">
// <div className="hero-body">
// <p className="title">
// Step 1
// </p>
// <p className="subtitle">
// Upload the file
// </p>
// </div>
// </section>
// <section className="section mb-5">
// <Dashboard
// uppy={uppy}
// theme='dark'
// proudlyDisplayPoweredByUppy={false}
// />
</div> // <input
// required
// hidden={true}
// style={{ display: 'none' }}
// className="input" type="text"
// {...register('files')}
// ></input>
</>
) // {errors.files && <p className="help is-danger">{errors.files.message?.toString()}</p>}
// </section>
// </div>}
// {(!isSubmitSuccessful) && <div className='column is-full '>
// {/* {(!cuid) && <aside className='notification is-info'>Hint: Some of these fields are filled out automatically when uploading from a <Link href="/streams">stream</Link> page.</aside>} */}
// <section className="hero is-info mb-3">
// <div className="hero-body">
// <p className="title">
// Step 2
// </p>
// <p className="subtitle">
// Tell us about the VOD
// </p>
// </div>
// </section>
// <section className="section">
// {/* <input
// required
// // hidden={false}
// // style={{ display: 'none' }}
// className="input" type="text"
// {...register('streamCuid')}
// ></input> */}
// <div className="field">
// <label className="label">VTuber</label>
// <div className="select">
// <select
// required
// // value={vtuber}
// // onChange={(evt) => setVtuber(parseInt(evt.target.value))}
// {...register('vtuber')}
// >
// {vtubers.map((vtuber: IVtuber) => (
// <option key={vtuber.id} value={vtuber.id}>{vtuber.attributes.displayName}</option>
// ))}
// </select>
// </div>
// <p className="help is-info">Choose the VTuber this VOD belongs to. (More VTubers will be added when storage/bandwidth funding is secured.)</p>
// {errors.vtuber && <p className="help is-danger">vtuber error</p>}
// </div>
// <div className="field">
// <label className="label">Stream Date</label>
// <input
// required
// className="input" type="date"
// {...register('date')}
// // onChange={(evt) => setDate(evt.target.value)}
// ></input>
// <p className="help is-info">The date when the VOD was originally streamed.</p>
// {errors.date && <p className="help is-danger">{errors.date.message?.toString()}</p>}
// </div>
// <div className="field">
// <label className="label">Notes</label>
// <textarea
// className="textarea"
// placeholder="e.g. Missing first 10 minutes of stream"
// // onChange={(evt) => setNote(evt.target.value)}
// {...register('notes')}
// ></textarea>
// <p className="help is-info">If there are any issues with the VOD, put a note here. If there are no VOD issues, leave this field blank.</p>
// </div>
// <div className="field">
// <label className="label">Attribution</label>
// <label className="checkbox">
// <input
// type="checkbox"
// // onChange={(evt) => setAttribution(evt.target.checked)}
// {...register('attribution')}
// />
// <span className={`ml-2 ${styles.noselect}`}>Credit {authData.user?.username} for the upload.</span>
// <p className="help is-info">Check this box if you want your username displayed on the website. Thank you for uploading!</p>
// </label>
// </div>
// </section>
// </div>}
// <div className="column is-full">
// <section className="hero is-info">
// <div className="hero-body">
// <p className="title">
// Step 3
// </p>
// <p className="subtitle">
// Send the form
// </p>
// </div>
// </section>
// <section className="section">
// {errors.root?.serverError && (
// <div className="notification">
// <button className="delete" onClick={() => clearErrors()}></button>
// <ErrorMessage name="root" errors={errors} ></ErrorMessage>
// </div>
// )}
// {!isSubmitSuccessful && (
// <button className="button is-primary is-large mt-5">
// <span className="icon is-small">
// <FontAwesomeIcon icon={faPaperPlane}></FontAwesomeIcon>
// </span>
// <span>Send</span>
// </button>
// )}
// {isSubmitting && (
// <p>
// <FontAwesomeIcon className="mt-5 fa-spin-pulse" icon={faSpinner} ></FontAwesomeIcon>
// </p>
// )}
// {isSubmitSuccessful && (
// <>
// <aside className="notification mt-5 is-success">Thank you for uploading! </aside>
// <button onClick={() => {
// reset(); // reset form
// const files = uppy.getFiles()
// for (const file of files) {
// uppy.removeFile(file.id); // reset uppy
// }
// }} className="button is-primary">
// <span className="icon is-small">
// <FontAwesomeIcon icon={faEraser}></FontAwesomeIcon>
// </span>
// <span>Reset form</span>
// </button>
// </>
// )}
// </section>
// </div>
// </form>
// </div>
// )
// }
// </div>
// </>
// )
} }

View File

@ -2,7 +2,6 @@
import { useEffect, useState, forwardRef, useContext, Ref } from 'react'; import { useEffect, useState, forwardRef, useContext, Ref } from 'react';
import { IVod } from '@/lib/vods'; import { IVod } from '@/lib/vods';
import "plyr-react/plyr.css";
import { useAuth } from '@/components/auth'; import { useAuth } from '@/components/auth';
import { getVodTitle } from './vod-page'; import { getVodTitle } from './vod-page';
import { VideoSourceSelector } from '@/components/video-source-selector' import { VideoSourceSelector } from '@/components/video-source-selector'
@ -123,7 +122,6 @@ export const VideoPlayer = forwardRef(function VideoPlayer( props: IPlayerProps,
src={src} src={src}
tokens={tokens} tokens={tokens}
primaryColor="#FFFFFF" primaryColor="#FFFFFF"
secondaryColor={hexToRgba(vod.attributes.vtuber.data.attributes.themeColor, 0.85)}
metadata={{ metadata={{
video_title: getVodTitle(vod) video_title: getVodTitle(vod)
}} }}

View File

@ -8,6 +8,7 @@ import Image from 'next/image'
import { LocalizedDate } from '@/components/localized-date' import { LocalizedDate } from '@/components/localized-date'
import { IMuxAsset, IMuxAssetResponse } from "@/lib/types"; import { IMuxAsset, IMuxAssetResponse } from "@/lib/types";
import { IB2File } from "@/lib/b2File"; import { IB2File } from "@/lib/b2File";
import VtuberButton from "./vtuber-button";
interface IVodCardProps { interface IVodCardProps {
id: number; id: number;
@ -42,22 +43,9 @@ export default function VodCard({id, title, date, muxAsset, thumbnail = 'https:/
</figure> </figure>
</div> </div>
<div className="card-content"> <div className="card-content">
<h1>{title}</h1> <p className="subtitle">{vtuber.attributes.displayName}</p>
<LocalizedDate date={new Date(date)} /> <LocalizedDate date={new Date(date)} />
<p className="">{title}</p>
<footer className="mt-3 card-footer">
<div className="card-footer-item">
<FontAwesomeIcon
icon={faVideo}
className="fas fa-video"
></FontAwesomeIcon>
</div>
{muxAsset && (
<div className="card-footer-item">
<FontAwesomeIcon icon={faPatreon} className="fab fa-patreon" />
</div>
)}
</footer>
</div> </div>
</Link> </Link>
</div> </div>

View File

@ -3,16 +3,18 @@ import { IVod } from '@/lib/vods';
import Link from 'next/link'; import Link from 'next/link';
import { VideoInteractive } from './video-interactive'; import { VideoInteractive } from './video-interactive';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faChevronLeft, faChevronRight, faGlobe, faLink } from "@fortawesome/free-solid-svg-icons"; import { faChevronLeft, faChevronRight, faGlobe, faImage, faLink } from "@fortawesome/free-solid-svg-icons";
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import { IpfsCid } from './ipfs-cid'; import { IpfsCid } from './ipfs-cid';
import LinkableHeading from './linkable-heading'; import LinkableHeading from './linkable-heading';
import Image from 'next/image';
import Thumbnail from './thumbnail';
export function getVodTitle(vod: IVod): string { export function getVodTitle(vod: IVod): string {
// console.log('lets getVodTitle, ey?') // console.log('lets getVodTitle, ey?')
// console.log(JSON.stringify(vod, null, 2)) // console.log(JSON.stringify(vod, null, 2))
return vod.attributes.title || vod.attributes.announceTitle || (vod.attributes?.date2 && vod.attributes?.vtuber?.data?.attributes?.displayName) ? `${vod.attributes.vtuber.data.attributes.displayName} ${vod.attributes.date2}` : `VOD ${vod.id}`; return vod.attributes?.title || vod.attributes?.announceTitle || `VOD ${vod.id}`
// return vod.attributes.title || vod.attributes.announceTitle || (vod.attributes?.date2 && vod.attributes?.vtuber?.data?.attributes?.displayName) ? `${vod.attributes.vtuber.data.attributes.displayName} ${vod.attributes.date2}` : `VOD ${vod.id}`;
} }
export function buildMuxUrl(playbackId: string, token: string) { export function buildMuxUrl(playbackId: string, token: string) {
@ -41,10 +43,14 @@ export default async function VodPage({vod}: { vod: IVod }) {
return ( return (
<div className="container"> <div className="container">
<div className="block"> <div className="block mb-5">
<div className="box">
<VideoInteractive vod={vod}></VideoInteractive> <VideoInteractive vod={vod}></VideoInteractive>
{(vod.attributes.thumbnail) && (<div className='mb-5'>
<LinkableHeading text="Thumbnail Image" slug="thumb" icon={faImage}></LinkableHeading>
<Thumbnail url={vod.attributes.thumbnail.data.attributes.cdnUrl}></Thumbnail>
</div>)}
{(vod.attributes.videoSrcHash || vod.attributes.video240Hash) && ( {(vod.attributes.videoSrcHash || vod.attributes.video240Hash) && (
<> <>
<LinkableHeading text="IPFS Content IDs" slug="ipfs" icon={faGlobe}></LinkableHeading> <LinkableHeading text="IPFS Content IDs" slug="ipfs" icon={faGlobe}></LinkableHeading>
@ -93,7 +99,6 @@ export default async function VodPage({vod}: { vod: IVod }) {
</nav> </nav>
</div>
</div> </div>
</div> </div>
); );

View File

@ -9,9 +9,9 @@ import LinkableHeading from '@/components/linkable-heading';
export default async function Page() { export default async function Page() {
return ( return (
<div className="content"> <div className="content">
<div className="block"> <div className="section">
<div className="box">
<p id="faq" className="title">Frequently Asked Questions (FAQ)</p> <p id="faq" className="title">Frequently Asked Questions (FAQ)</p>
</div>
@ -98,7 +98,5 @@ export default async function Page() {
</div> </div>
</div> </div>
</div>
</div>
) )
} }

View File

@ -34,10 +34,13 @@ export default async function Page() {
<> <>
<div className="content"> <div className="content">
<div className="block"> <div className="block">
<div className="box">
<div className="section">
<h1 className="title">Goals</h1> <h1 className="title">Goals</h1>
<p className="subtitle mt-5"> <p className="subtitle">Shooting for the stars</p>
</div>
<div className="section">
<p className="title is-size-4">
<span>In Progress</span> <span>In Progress</span>
</p> </p>
<ul className=""> <ul className="">
@ -47,8 +50,10 @@ export default async function Page() {
</li> </li>
))} ))}
</ul> </ul>
<p className="subtitle mt-5"> </div>
<span>Planned</span> <div className="section">
<p className="title is-size-4">
Planned
</p> </p>
<ul className=""> <ul className="">
{planned.map((goal) => ( {planned.map((goal) => (
@ -57,7 +62,9 @@ export default async function Page() {
</li> </li>
))} ))}
</ul> </ul>
<p className="subtitle mt-5"> </div>
<div className="section">
<p className="title is-size-4">
<span>Completed</span> <span>Completed</span>
</p> </p>
<ul className=""> <ul className="">

View File

@ -1,7 +1,8 @@
import { ReactNode } from 'react' import { ReactNode } from 'react'
import Footer from "./components/footer" import Footer from "./components/footer"
import Navbar from "./components/navbar" import Navbar from "./components/navbar"
import "../assets/styles/global.sass"; import "bulma"
import "../assets/styles/global.css";
import "@fortawesome/fontawesome-svg-core/styles.css"; import "@fortawesome/fontawesome-svg-core/styles.css";
import { AuthProvider } from './components/auth'; import { AuthProvider } from './components/auth';
import type { Metadata } from 'next'; import type { Metadata } from 'next';

View File

@ -78,13 +78,10 @@ export async function getVodFromSafeDateOrCuid(safeDateOrCuid: string): Promise<
vod = await getVodByCuid(safeDateOrCuid); vod = await getVodByCuid(safeDateOrCuid);
if (!vod) return null; if (!vod) return null;
} else { } else {
console.log('This is a safeDate!');
date = await getDateFromSafeDate(safeDateOrCuid); date = await getDateFromSafeDate(safeDateOrCuid);
if (!date) { if (!date) {
console.log('there is no date') console.log('there is no date')
return null; return null;
} else {
console.log(`date=${date}`)
} }
vod = await getVodForDate(date); vod = await getVodForDate(date);
} }
@ -92,7 +89,7 @@ export async function getVodFromSafeDateOrCuid(safeDateOrCuid: string): Promise<
} }
export function getUrl(vod: IVod, slug: string, date: string): string { export function getUrl(vod: IVod, slug: string, date: string): string {
return `${siteUrl}/vt/${slug}/vod/${getSafeDate(date)}` return `/vt/${slug}/vod/${getSafeDate(date)}`
} }

View File

@ -33,11 +33,9 @@ export default async function Page() {
</div> </div>
</section> </section>
<section className="section">
<FundingGoal /> <FundingGoal />
</section>
<section className="section"> <div className="section">
<h2 className="is-2 title">Latest VODs</h2> <h2 className="is-2 title">Latest VODs</h2>
<div className="columns is-multiline is-mobile"> <div className="columns is-multiline is-mobile">
@ -56,16 +54,16 @@ export default async function Page() {
</div> </div>
<Link className='button' href={`/latest-vods/1`}>See all Latest Vods</Link> <Link className='button' href={`/latest-vods/1`}>See all Latest Vods</Link>
</section> </div>
<section className="section"> <div className="section">
<h2 className="is-2 title">VTubers</h2> <h2 className="is-2 title">VTubers</h2>
{/* <nav className="columns is-multiline"> <nav className="columns is-multiline">
{vtubers.data.map((vtuber: IVtuber) => {vtubers.data.map((vtuber: IVtuber) =>
<VTuberCard key={vtuber.id} {...vtuber} /> <VTuberCard key={vtuber.id} {...vtuber} />
)} )}
</nav> */} </nav>
</section> </div>
</div> </div>
</> </>
); );

View File

@ -13,15 +13,18 @@ export default async function Page() {
<> <>
<div className="content"> <div className="content">
<div className="block"> <div className="block">
<div className="box"> <div className='section'>
<h1 className="title">Patron List</h1> <h1 className="title">Patron List</h1>
<p className="subtitle"> <p className="subtitle">
<span>Futureporn.net continues to improve thanks to </span> <span>Futureporn.net continues to improve thanks to </span>
<strong>{patreonCampaign.patronCount} generous supporters.</strong> <strong>{patreonCampaign.patronCount} generous supporters.</strong>
</p> </p>
</div>
<div className='section'>
<PatronsList displayStyle="box" /> <PatronsList displayStyle="box" />
<div className='box'>
<p>Want to get your name on this list, and get perks like FAST video streaming?</p> <p>Want to get your name on this list, and get perks like FAST video streaming?</p>
<Link target="_blank" rel="noopener noreferrer" href="https://patreon.com/CJ_Clippy" className='button is-primary mb-3'> <Link target="_blank" rel="noopener noreferrer" href="https://patreon.com/CJ_Clippy" className='button is-primary mb-3'>
<span className="mr-1">Become a patron today!</span> <span className="mr-1">Become a patron today!</span>
@ -37,6 +40,7 @@ export default async function Page() {
</div> </div>
</div> </div>
</div> </div>
</div>
</> </>
); );
} }

View File

@ -6,7 +6,7 @@ export default async function Page() {
return ( return (
<div className="content"> <div className="content">
<div className="box"> <div className="section">
<h2>Tags</h2> <h2>Tags</h2>
<SortableTags tags={tags}/> <SortableTags tags={tags}/>
</div> </div>

View File

@ -1,6 +1,7 @@
import { getAllVtubers } from '@/lib/vtubers'; import { getAllVtubers } from '@/lib/vtubers';
import UploadForm from '@/components/upload-form'; import UploadForm from '@/components/upload-form';
import { Suspense } from 'react';
import '@uppy/core/dist/style.min.css'; import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css'; import '@uppy/dashboard/dist/style.min.css';
@ -11,14 +12,15 @@ export default async function Page() {
const vtubers = await getAllVtubers(); const vtubers = await getAllVtubers();
if (!vtubers) return (
<aside className='notification is-danger'>Failed to fetch vtubers list. Please try again later.</aside>
)
return ( return (
<> <>
{!vtubers <Suspense>
? <aside className='notification is-danger'>Failed to fetch vtubers list. Please try again later.</aside> <UploadForm vtubers={vtubers}></UploadForm>
: <UploadForm vtubers={vtubers}></UploadForm> </Suspense>
}
</> </>

View File

@ -17,7 +17,6 @@ import styles from '@/assets/styles/icon.module.css';
import { getVodsForVtuber } from '@/lib/vods'; import { getVodsForVtuber } from '@/lib/vods';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import ArchiveProgress from '@/components/archive-progress'; import ArchiveProgress from '@/components/archive-progress';
import StreamsCalendar from '@/components/streams-calendar';
import { getAllStreamsForVtuber, getStreamsForVtuber } from '@/lib/streams'; import { getAllStreamsForVtuber, getStreamsForVtuber } from '@/lib/streams';
import LinkableHeading from '@/components/linkable-heading'; import LinkableHeading from '@/components/linkable-heading';
@ -52,7 +51,7 @@ export default async function Page({ params }: { params: { slug: string } }) {
<> <>
{vtuber && ( {vtuber && (
<> <>
<div className="box"> <div className="section">
<div className="columns is-multiline"> <div className="columns is-multiline">
<div className="column is-full"> <div className="column is-full">
@ -223,21 +222,11 @@ export default async function Page({ params }: { params: { slug: string } }) {
<VodsList vtuber={vtuber} vods={vods.data} page={1} pageSize={9} /> <VodsList vtuber={vtuber} vods={vods.data} page={1} pageSize={9} />
{ {
(vtuber.attributes.vods) ? ( (vods.data) ? (
<Link className='button mb-5' href={`/vt/${vtuber.attributes.slug}/vods/1`}>See all {vtuber.attributes.displayName} vods</Link> <Link className='button mb-5' href={`/vt/${vtuber.attributes.slug}/vods/1`}>See all {vtuber.attributes.displayName} vods</Link>
) : (<p className='section'><i>No VODs have been added, yet.</i></p>) ) : (<p className='section'><i>No VODs have been added, yet.</i></p>)
} }
{/* <h2 id="streams" className='title is-3'>
<Link href="#streams">Streams</Link>
</h2> */}
{/* <StreamsCalendar missingStreams={missingStreams} issueStreams={issueStreams} goodStreams={goodStreams} /> */}
{/*
<h2 id="progress" className='title is-3'>
<Link href="#progress">Archive Progress</Link>
</h2>
<ArchiveProgress vtuber={vtuber} /> */}
</div> </div>
</> </>

View File

@ -1,89 +0,0 @@
$cell-height : 10px;
$cell-width : 10px;
$cell-margin:2px;
$cell-weekdays-width: 30px;
html {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
html, body {
height: 100%;
width: 100%;
}
#container {
height: 514px;
width: 930px;
margin: 50px auto;
}
.timeline {
margin: 20px;
margin-bottom: 60px;
.timeline-months {
display: flex;
padding-left: $cell-weekdays-width;
&-month {
width: $cell-width;
margin: $cell-margin;
border: 1px solid transparent;
font-size: 10px;
}
.Jan~.Jan,
.Feb~.Feb,
.Mar~.Mar,
.Apr~.Apr,
.May~.May,
.Jun~.Jun,
.Jul~.Jul,
.Aug~.Aug,
.Sep~.Sep,
.Oct~.Oct,
.Nov~.Nov,
.Dec~.Dec {
visibility: hidden;
}
}
&-body {
display: flex;
.timeline-weekdays {
display: inline-flex;
flex-direction: column;
width: $cell-weekdays-width;
&-weekday {
font-size: 10px;
height: $cell-height;
border: 1px solid transparent;
margin: $cell-margin;
vertical-align: middle;
}
}
.timeline-cells {
display: inline-flex;
flex-direction: column;
flex-wrap: wrap;
height: #{(10 + 4) * 8}px;
&-cell {
height: $cell-height;
width: $cell-width;
border: 1px solid rgba(0, 0, 0, 0.1);
margin: $cell-margin;
border-radius: 2px;
background-color: rgba(0, 0, 0, 0.05);
&:hover {
border: 1px solid rgba(0, 0, 0, 0.3);
}
}
}
}
}

View File

@ -18,3 +18,11 @@
font-size: 8rem; font-size: 8rem;
font-weight: bolder; font-weight: bolder;
} }
.zoomin {
cursor: zoom-in;
}
.zoomout {
cursor: zoom-out;
}

View File

@ -7,16 +7,25 @@
src: url('/fonts/nunito-v26-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ src: url('/fonts/nunito-v26-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
/*
palleton color scheme
https://paletton.com/#uid=54W0u0kv5npmjustvtxAGj4KwdK
*/
:root { :root {
/* mux player styling */
--media-accent-color: #fb00ff;
/* this brightens message headers (funding goal) which by default were too close to the bg color */
--bulma-dark-l: 22%;
/* Colors and Lightness values */ /* Colors and Lightness values */
--bulma-scheme-h: 221; --bulma-scheme-h: 221;
--bulma-scheme-s: 14%; --bulma-scheme-s: 14%;
--bulma-light-l: 90%; --bulma-light-l: 90%;
--bulma-light-invert-l: 20%; --bulma-light-invert-l: 20%;
--bulma-dark-l: 10%; --bulma-dark-invert-l: 90%;
--bulma-dark-invert-l: 0%;
--bulma-soft-l: 90%; --bulma-soft-l: 90%;
--bulma-bold-l: 20%; --bulma-bold-l: 20%;
--bulma-soft-invert-l: 20%; --bulma-soft-invert-l: 20%;
@ -27,15 +36,15 @@
--bulma-primary: hsla(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l), 1); --bulma-primary: hsla(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l), 1);
--bulma-primary-base: hsla(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l), 1); --bulma-primary-base: hsla(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-l), 1);
--bulma-primary-rgb: 0, 209, 178; --bulma-primary-rgb: 0, 209, 178;
--bulma-primary-h: 171deg; --bulma-primary-h: 299deg;
--bulma-primary-s: 100%; --bulma-primary-s: 50%;
--bulma-primary-l: 41%; --bulma-primary-l: 50%;
--bulma-primary-00-l: 1%; --bulma-primary-00-l: 1%;
--bulma-primary-05-l: 6%; --bulma-primary-05-l: 6%;
--bulma-primary-10-l: 11%; --bulma-primary-10-l: 11%;
--bulma-primary-15-l: 16%; --bulma-primary-15-l: 16%;
--bulma-primary-20-l: 21%; --bulma-primary-20-l: 21%;
/* etc. */ --bulma-info-l: 50%;
/* Typography */ /* Typography */
--bulma-family-primary: Nunito, Inter, SF Pro, Segoe UI, Roboto, Oxygen, Ubuntu, Helvetica Neue, Helvetica, Arial, sans-serif; --bulma-family-primary: Nunito, Inter, SF Pro, Segoe UI, Roboto, Oxygen, Ubuntu, Helvetica Neue, Helvetica, Arial, sans-serif;

View File

@ -15,63 +15,54 @@
"@fortawesome/free-brands-svg-icons": "^6.5.1", "@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@fullcalendar/core": "^6.1.10",
"@fullcalendar/daygrid": "^6.1.10",
"@fullcalendar/interaction": "^6.1.10",
"@fullcalendar/multimonth": "^6.1.10",
"@fullcalendar/react": "^6.1.10",
"@hookform/error-message": "^2.0.1", "@hookform/error-message": "^2.0.1",
"@hookform/resolvers": "^3.3.4", "@hookform/resolvers": "^3.3.4",
"@mux/blurhash": "^0.1.2", "@mux/blurhash": "^0.1.2",
"@mux/mux-player": "^2.3.1", "@mux/mux-player": "^2.4.0",
"@mux/mux-player-react": "^2.3.1", "@mux/mux-player-react": "^2.4.0",
"@paralleldrive/cuid2": "^2.2.2", "@paralleldrive/cuid2": "^2.2.2",
"@react-hookz/web": "^24.0.2", "@react-hookz/web": "^24.0.4",
"@tanstack/react-table": "^8.11.7", "@tanstack/react-table": "^8.15.0",
"@types/lodash": "^4.14.202", "@types/lodash": "^4.17.0",
"@types/qs": "^6.9.11", "@types/qs": "^6.9.14",
"@types/react": "^18.2.47", "@types/react": "^18.2.73",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.22",
"@uppy/aws-s3": "^3.6.0", "@uppy/aws-s3": "^3.6.2",
"@uppy/aws-s3-multipart": "^3.3.0", "@uppy/aws-s3-multipart": "^3.11.0",
"@uppy/core": "^3.8.0", "@uppy/core": "^3.10.0",
"@uppy/dashboard": "^3.7.1", "@uppy/dashboard": "^3.8.0",
"@uppy/drag-drop": "^3.0.3", "@uppy/drag-drop": "^3.1.0",
"@uppy/file-input": "^3.0.4", "@uppy/file-input": "^3.1.0",
"@uppy/progress-bar": "^3.0.4", "@uppy/progress-bar": "^3.1.1",
"@uppy/react": "^3.2.1", "@uppy/react": "^3.3.0",
"@uppy/remote-sources": "^1.1.0", "@uppy/remote-sources": "^1.2.0",
"bulma": "^0.9.4", "bulma": "^1.0.0",
"bulma-prefers-dark": "0.1.0-beta.1", "date-fns": "^2.30.0",
"date-fns": "^2.0.0", "date-fns-tz": "^2.0.1",
"date-fns-tz": "^2.0.0",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"feed": "^4.2.2", "feed": "^4.2.2",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"hls.js": "^1.5.1", "hls.js": "^1.5.7",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lunarphase-js": "^2.0.1", "lunarphase-js": "^2.0.3",
"multiformats": "^13.0.1", "multiformats": "^13.1.0",
"next": "^14.0.4", "next": "14.0.4",
"next-goatcounter": "^1.0.5", "next-goatcounter": "^1.0.5",
"nextjs-toploader": "^1.6.4", "nextjs-toploader": "^1.6.11",
"plyr": "^3.7.8",
"plyr-react": "^5.3.0",
"prism-react-renderer": "^2.3.1", "prism-react-renderer": "^2.3.1",
"qs": "^6.11.2", "qs": "^6.12.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hook-form": "^7.49.3", "react-hook-form": "^7.51.2",
"react-loading-skeleton": "^3.3.1", "react-loading-skeleton": "^3.4.0",
"react-toastify": "^9.1.3", "react-toastify": "^9.1.3",
"sass": "^1.69.7", "sharp": "^0.33.3",
"sharp": "^0.33.2",
"slugify": "^1.6.6", "slugify": "^1.6.6",
"yup": "^1.3.3" "yup": "^1.4.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.11.0", "@types/node": "^20.11.30",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"eslint-config-next": "14.0.4", "eslint-config-next": "14.0.4",
"tsc": "^2.0.4", "tsc": "^2.0.4",
"typescript": "5.3.3" "typescript": "5.3.3"

View File

@ -20,21 +20,6 @@ dependencies:
'@fortawesome/react-fontawesome': '@fortawesome/react-fontawesome':
specifier: ^0.2.0 specifier: ^0.2.0
version: 0.2.0(@fortawesome/fontawesome-svg-core@6.5.1)(react@18.2.0) version: 0.2.0(@fortawesome/fontawesome-svg-core@6.5.1)(react@18.2.0)
'@fullcalendar/core':
specifier: ^6.1.11
version: 6.1.11
'@fullcalendar/daygrid':
specifier: ^6.1.11
version: 6.1.11(@fullcalendar/core@6.1.11)
'@fullcalendar/interaction':
specifier: ^6.1.11
version: 6.1.11(@fullcalendar/core@6.1.11)
'@fullcalendar/multimonth':
specifier: ^6.1.11
version: 6.1.11(@fullcalendar/core@6.1.11)
'@fullcalendar/react':
specifier: ^6.1.11
version: 6.1.11(@fullcalendar/core@6.1.11)(react-dom@18.2.0)(react@18.2.0)
'@hookform/error-message': '@hookform/error-message':
specifier: ^2.0.1 specifier: ^2.0.1
version: 2.0.1(react-dom@18.2.0)(react-hook-form@7.51.2)(react@18.2.0) version: 2.0.1(react-dom@18.2.0)(react-hook-form@7.51.2)(react@18.2.0)
@ -130,19 +115,13 @@ dependencies:
version: 13.1.0 version: 13.1.0
next: next:
specifier: 14.0.4 specifier: 14.0.4
version: 14.0.4(react-dom@18.2.0)(react@18.2.0)(sass@1.72.0) version: 14.0.4(react-dom@18.2.0)(react@18.2.0)
next-goatcounter: next-goatcounter:
specifier: ^1.0.5 specifier: ^1.0.5
version: 1.0.5(next@14.0.4)(react-dom@18.2.0)(react@18.2.0) version: 1.0.5(next@14.0.4)(react-dom@18.2.0)(react@18.2.0)
nextjs-toploader: nextjs-toploader:
specifier: ^1.6.11 specifier: ^1.6.11
version: 1.6.11(next@14.0.4)(react-dom@18.2.0)(react@18.2.0) version: 1.6.11(next@14.0.4)(react-dom@18.2.0)(react@18.2.0)
plyr:
specifier: ^3.7.8
version: 3.7.8
plyr-react:
specifier: ^5.3.0
version: 5.3.0(plyr@3.7.8)(react@18.2.0)
prism-react-renderer: prism-react-renderer:
specifier: ^2.3.1 specifier: ^2.3.1
version: 2.3.1(react@18.2.0) version: 2.3.1(react@18.2.0)
@ -164,9 +143,6 @@ dependencies:
react-toastify: react-toastify:
specifier: ^9.1.3 specifier: ^9.1.3
version: 9.1.3(react-dom@18.2.0)(react@18.2.0) version: 9.1.3(react-dom@18.2.0)(react@18.2.0)
sass:
specifier: ^1.72.0
version: 1.72.0
sharp: sharp:
specifier: ^0.33.3 specifier: ^0.33.3
version: 0.33.3 version: 0.33.3
@ -299,49 +275,6 @@ packages:
react: 18.2.0 react: 18.2.0
dev: false dev: false
/@fullcalendar/core@6.1.11:
resolution: {integrity: sha512-TjG7c8sUz+Vkui2FyCNJ+xqyu0nq653Ibe99A66LoW95oBo6tVhhKIaG1Wh0GVKymYiqAQN/OEdYTuj4ay27kA==}
dependencies:
preact: 10.12.1
dev: false
/@fullcalendar/daygrid@6.1.11(@fullcalendar/core@6.1.11):
resolution: {integrity: sha512-hF5jJB7cgUIxWD5MVjj8IU407HISyLu7BWXcEIuTytkfr8oolOXeCazqnnjmRbnFOncoJQVstTtq6SIhaT32Xg==}
peerDependencies:
'@fullcalendar/core': ~6.1.11
dependencies:
'@fullcalendar/core': 6.1.11
dev: false
/@fullcalendar/interaction@6.1.11(@fullcalendar/core@6.1.11):
resolution: {integrity: sha512-ynOKjzuPwEAMgTQ6R/Z2zvzIIqG4p8/Qmnhi1q0vzPZZxSIYx3rlZuvpEK2WGBZZ1XEafDOP/LGfbWoNZe+qdg==}
peerDependencies:
'@fullcalendar/core': ~6.1.11
dependencies:
'@fullcalendar/core': 6.1.11
dev: false
/@fullcalendar/multimonth@6.1.11(@fullcalendar/core@6.1.11):
resolution: {integrity: sha512-7DbPC+AAlaKnquGVdw1Z85Q3nSZ4GZ1NcVIk4k7bLnqDlntwHPPsrDlSIzUWKcN0q5/u7jQHm4PU1m3LAl70Sg==}
peerDependencies:
'@fullcalendar/core': ~6.1.11
dependencies:
'@fullcalendar/core': 6.1.11
'@fullcalendar/daygrid': 6.1.11(@fullcalendar/core@6.1.11)
dev: false
/@fullcalendar/react@6.1.11(@fullcalendar/core@6.1.11)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-Og0Tv0OiglTFp+b++yRyEhAeWnAmKkMLQ3iS0eJE1KDEov6QqGkoO+dUG4x8zp2w55IJqzik/a9iHi0s3oQDbA==}
peerDependencies:
'@fullcalendar/core': ~6.1.11
react: ^16.7.0 || ^17 || ^18
react-dom: ^16.7.0 || ^17 || ^18
dependencies:
'@fullcalendar/core': 6.1.11
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@hookform/error-message@2.0.1(react-dom@18.2.0)(react-hook-form@7.51.2)(react@18.2.0): /@hookform/error-message@2.0.1(react-dom@18.2.0)(react-hook-form@7.51.2)(react@18.2.0):
resolution: {integrity: sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==} resolution: {integrity: sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==}
peerDependencies: peerDependencies:
@ -1579,11 +1512,6 @@ packages:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: true dev: true
/core-js@3.36.1:
resolution: {integrity: sha512-BTvUrwxVBezj5SZ3f10ImnX2oRByMxql3EimVqMysepbC9EeMUOpLwdy6Eoili2x6E4kf+ZUB5k/+Jv55alPfA==}
requiresBuild: true
dev: false
/cross-spawn@7.0.3: /cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -1597,10 +1525,6 @@ packages:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
dev: false dev: false
/custom-event-polyfill@1.0.7:
resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==}
dev: false
/custom-media-element@1.2.3: /custom-media-element@1.2.3:
resolution: {integrity: sha512-xr9Hbrslkjm1fapJP5hL98pySeZmNepBSefQS/XTxynamqPTfRBK5MnhReMOiAj8xvJApVPrVnlYxIrknay8jg==} resolution: {integrity: sha512-xr9Hbrslkjm1fapJP5hL98pySeZmNepBSefQS/XTxynamqPTfRBK5MnhReMOiAj8xvJApVPrVnlYxIrknay8jg==}
dev: false dev: false
@ -2781,10 +2705,6 @@ packages:
type-check: 0.4.0 type-check: 0.4.0
dev: true dev: true
/loadjs@4.2.0:
resolution: {integrity: sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==}
dev: false
/locate-path@6.0.0: /locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -2919,12 +2839,12 @@ packages:
react: '>18.0.0' react: '>18.0.0'
react-dom: '>18.0.0' react-dom: '>18.0.0'
dependencies: dependencies:
next: 14.0.4(react-dom@18.2.0)(react@18.2.0)(sass@1.72.0) next: 14.0.4(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
dev: false dev: false
/next@14.0.4(react-dom@18.2.0)(react@18.2.0)(sass@1.72.0): /next@14.0.4(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==} resolution: {integrity: sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==}
engines: {node: '>=18.17.0'} engines: {node: '>=18.17.0'}
hasBin: true hasBin: true
@ -2947,7 +2867,6 @@ packages:
postcss: 8.4.31 postcss: 8.4.31
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
sass: 1.72.0
styled-jsx: 5.1.1(react@18.2.0) styled-jsx: 5.1.1(react@18.2.0)
watchpack: 2.4.0 watchpack: 2.4.0
optionalDependencies: optionalDependencies:
@ -2973,7 +2892,7 @@ packages:
react-dom: '>= 16.0.0' react-dom: '>= 16.0.0'
dependencies: dependencies:
'@types/nprogress': 0.2.3 '@types/nprogress': 0.2.3
next: 14.0.4(react-dom@18.2.0)(react@18.2.0)(sass@1.72.0) next: 14.0.4(react-dom@18.2.0)(react@18.2.0)
nprogress: 0.2.0 nprogress: 0.2.0
prop-types: 15.8.1 prop-types: 15.8.1
react: 18.2.0 react: 18.2.0
@ -3160,31 +3079,6 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
/plyr-react@5.3.0(plyr@3.7.8)(react@18.2.0):
resolution: {integrity: sha512-m36/HrpHwg1N2rq3E31E8/kpAH55vk6qHUg17MG4uu9jbWYxnkN39lLmZQwxW7/qpDPfW5aGUJ6R3u23V0R3zA==}
engines: {node: '>=16'}
peerDependencies:
plyr: ^3.7.7
react: '>=16.8'
peerDependenciesMeta:
react:
optional: true
dependencies:
plyr: 3.7.8
react: 18.2.0
react-aptor: 2.0.0(react@18.2.0)
dev: false
/plyr@3.7.8:
resolution: {integrity: sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==}
dependencies:
core-js: 3.36.1
custom-event-polyfill: 1.0.7
loadjs: 4.2.0
rangetouch: 2.0.1
url-polyfill: 1.1.12
dev: false
/possible-typed-array-names@1.0.0: /possible-typed-array-names@1.0.0:
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -3199,10 +3093,6 @@ packages:
source-map-js: 1.2.0 source-map-js: 1.2.0
dev: false dev: false
/preact@10.12.1:
resolution: {integrity: sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==}
dev: false
/preact@10.20.1: /preact@10.20.1:
resolution: {integrity: sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw==} resolution: {integrity: sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw==}
dev: false dev: false
@ -3275,10 +3165,6 @@ packages:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true dev: true
/rangetouch@2.0.1:
resolution: {integrity: sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==}
dev: false
/rc@1.2.8: /rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true hasBin: true
@ -3289,18 +3175,6 @@ packages:
strip-json-comments: 2.0.1 strip-json-comments: 2.0.1
dev: false dev: false
/react-aptor@2.0.0(react@18.2.0):
resolution: {integrity: sha512-YnCayokuhAwmBBP4Oc0bbT2l6ApfsjbY3DEEVUddIKZEBlGl1npzjHHzWnSqWuboSbMZvRqUM01Io9yiIp1wcg==}
engines: {node: '>=12.7.0'}
peerDependencies:
react: '>=16.8'
peerDependenciesMeta:
react:
optional: true
dependencies:
react: 18.2.0
dev: false
/react-dom@18.2.0(react@18.2.0): /react-dom@18.2.0(react@18.2.0):
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies: peerDependencies:
@ -3902,10 +3776,6 @@ packages:
punycode: 2.3.1 punycode: 2.3.1
dev: true dev: true
/url-polyfill@1.1.12:
resolution: {integrity: sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==}
dev: false
/util-deprecate@1.0.2: /util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: false dev: false

View File

@ -1,8 +0,0 @@
.tmp/
.cache/
.git/
build/
node_modules/
.env
data/
backup/

1
packages/strapi/.npmrc Normal file
View File

@ -0,0 +1 @@
shamefully-hoist=true

View File

@ -1,19 +1,28 @@
FROM node:18.16-alpine # Creating multi-stage build for production
# Installing libvips-dev for sharp Compatibility FROM node:18-alpine as build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
ARG NODE_ENV=development ENV NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/ WORKDIR /opt/
COPY package.json yarn.lock ./ COPY package.json yarn.lock ./
RUN yarn config set network-timeout 600000 -g && yarn install RUN yarn global add node-gyp
RUN yarn config set network-timeout 600000 -g && yarn install --production
ENV PATH /opt/node_modules/.bin:$PATH
WORKDIR /opt/app WORKDIR /opt/app
COPY . . COPY . .
RUN yarn build
# Creating final production image
FROM node:18-alpine
RUN apk add --no-cache vips-dev
ENV NODE_ENV=production
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
ENV PATH /opt/node_modules/.bin:$PATH ENV PATH /opt/node_modules/.bin:$PATH
RUN chown -R node:node /opt/app RUN chown -R node:node /opt/app
USER node USER node
RUN ["yarn", "build"]
EXPOSE 1337 EXPOSE 1337
# CMD ["yarn", "develop"] CMD ["yarn", "start"]
CMD yarn develop

View File

@ -0,0 +1,26 @@
FROM node:18.16-alpine as base
RUN corepack enable
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}
WORKDIR /app
FROM base AS build
COPY package.json pnpm-lock.yaml ./
# RUN yarn config set network-timeout 600000 -g && yarn install
RUN pnpm install --frozen-lockfile
COPY . .
ENV PATH=/app/node_modules/.bin:$PATH
RUN chown -R node:node /app
USER node
RUN pnpm run build
EXPOSE 1337
FROM build AS dev
CMD ["pnpm", "run", "dev"]
FROM build AS release
ENTRYPOINT ["pnpm", "run", "start"]

View File

@ -0,0 +1,31 @@
# Creating multi-stage build for production
FROM node:18-alpine as build
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
ENV NODE_ENV=production
WORKDIR /opt/
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --prod
ENV PATH /opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN pnpm run build
# Creating final production image
FROM node:18-alpine
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
RUN apk add --no-cache vips-dev
ENV NODE_ENV=production
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
ENV PATH /opt/node_modules/.bin:$PATH
RUN chown -R node:node /opt/app
USER node
EXPOSE 1337
CMD ["pnpm", "start"]

View File

@ -0,0 +1,19 @@
FROM node:18-alpine
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json yarn.lock ./
RUN yarn global add node-gyp
RUN yarn config set network-timeout 600000 -g && yarn install
ENV PATH /opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["yarn", "build"]
EXPOSE 1337
CMD ["yarn", "dev"]

View File

@ -4,15 +4,14 @@
"version": "0.1.0", "version": "0.1.0",
"description": "A Strapi application", "description": "A Strapi application",
"scripts": { "scripts": {
"dev": "yarn strapi develop",
"dev:c": "concurrently \"npm:tunnel\" \"npm:dev:strapi\"", "dev:c": "concurrently \"npm:tunnel\" \"npm:dev:strapi\"",
"tunnel": "ngrok start futureporn-strapi", "tunnel": "ngrok start futureporn-strapi",
"chisel": "bash ./chisel.sh", "chisel": "bash ./chisel.sh",
"db": "bash ./database/devDb.sh", "db": "bash ./database/devDb.sh",
"start": "strapi start", "start": "strapi start",
"build": "strapi build", "build": "strapi build",
"develop": "NODE_ENV=development strapi develop", "strapi": "strapi"
"strapi": "strapi",
"preinstall": "npx only-allow yarn"
}, },
"dependencies": { "dependencies": {
"@11ty/eleventy-fetch": "^4.0.0", "@11ty/eleventy-fetch": "^4.0.0",
@ -85,6 +84,5 @@
"node": ">=14.19.1 <=18.x.x", "node": ">=14.19.1 <=18.x.x",
"npm": ">=6.0.0" "npm": ">=6.0.0"
}, },
"license": "MIT", "license": "MIT"
"packageManager": "yarn@1.22.19"
} }

13135
packages/strapi/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,9 @@
const { S3Client, DeleteObjectCommand } = require("@aws-sdk/client-s3"); const { S3Client, DeleteObjectCommand } = require("@aws-sdk/client-s3");
require('dotenv').config()
if (!process.env.S3_USC_BUCKET_NAME) throw new Error('S3_USC_BUCKET_NAME must be defined in env'); if (!process.env.S3_USC_BUCKET_NAME) throw new Error('S3_USC_BUCKET_NAME must be defined in env');
if (!process.env.S3_USC_BUCKET_ENDPOINT) throw new Error('S3_USC_BUCKET_ENDPOINT must be defined in env'); if (!process.env.S3_USC_BUCKET_ENDPOINT) throw new Error('S3_USC_BUCKET_ENDPOINT must be defined in env');
if (!process.env.S3_USC_BUCKET_REGION) throw new Error('S3_USC_BUCKET_REGION must be defined in env'); if (!process.env.S3_USC_BUCKET_REGION) throw new Error('S3_USC_BUCKET_REGION must be defined in env');
if (!process.env.AWS_ACCESS_KEY_ID) throw new Error('AWS_ACCESS_KEY_ID must be defined in env');
if (!process.env.AWS_SECRET_ACCESS_KEY) throw new Error('AWS_SECRET_ACCESS_KEY must be defined in env');
// AWS.config.loadFromPath('./credentials-ehl.json'); // AWS.config.loadFromPath('./credentials-ehl.json');

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
require('dotenv').config()
if (!process.env.CDN_BUCKET_USC_URL) throw new Error('CDN_BUCKET_USC_URL environment variable is required!'); if (!process.env.CDN_BUCKET_USC_URL) throw new Error('CDN_BUCKET_USC_URL environment variable is required!');

File diff suppressed because it is too large Load Diff

3172
packages/uppy/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
packages: packages:
- 'packages/next'
- 'packages/uppy' - 'packages/uppy'
- 'packages/bot' - 'packages/bot'
- 'packages/next'
# strapi is not on here because it's not compatible with pnpm # strapi is not on here because it's not compatible with pnpm