Compare commits

..

26 Commits

Author SHA1 Message Date
ac751f5f28 adding prefers reduced motion and clamp width to percent between values on body 2024-08-12 12:44:35 -06:00
a1aecdf3e2 adding AbuseIPDB to composer list 2024-08-12 12:43:44 -06:00
a747ef0129 adding a security.txt file 2024-03-18 11:18:25 -06:00
80aa487e7e updating some status codes 2024-02-28 14:52:37 -07:00
5048abc3e6 adding some text gradient CSS 2023-12-12 14:00:23 -07:00
afd34e9b4e adding profile photo trait 2023-12-12 13:59:55 -07:00
a81ce8a922 adding glossy button CSS 2023-12-12 13:59:44 -07:00
9d25befeba adding a method to also generate an avatar for a user 2023-12-12 13:58:31 -07:00
5d9f7e3997 adding package to convert heic/heif to jpeg, also paperclip 2023-12-12 13:58:10 -07:00
ecfae3e01a using new style of attribute casting 2023-12-12 13:57:42 -07:00
9e6c93ba95 adding some defaults to image tags 2023-12-12 13:57:12 -07:00
231dd959af adding some gradient border CSS 2023-12-12 13:56:57 -07:00
5607425bde adding a security template file 2023-12-12 13:56:38 -07:00
ac99d29109 removing unnecessary code to properly extend Jetstream user profile controller 2023-03-27 10:24:09 -06:00
d4f0044656 moving to mailpit from mailhog, adding paths to SSLs 2023-03-27 10:23:28 -06:00
9d455bdcf7 moving around some stuff with PHPCS config file 2023-03-27 10:22:57 -06:00
3b39ae0470 adding require pin package 2023-03-27 10:22:07 -06:00
9551f661c1 adding more colors 2023-03-27 10:21:52 -06:00
c02b40071f adding some colors as a markdown file 2023-03-27 10:21:34 -06:00
a0dc0e01f3 adding an action for genering profile photos 2023-03-27 10:21:08 -06:00
8876f07ac6 fixing some text and height stuff for the body tag 2023-03-27 10:20:56 -06:00
2ac78ef539 adding some variables for colors 2023-03-27 10:20:41 -06:00
56cef79880 fixing path to SSLs 2023-03-27 10:20:09 -06:00
aa5753cc82 adding a Vite SSR file 2023-03-27 10:19:55 -06:00
4dcb6b6ebe adding a clamp function 2023-03-27 10:19:42 -06:00
22946bc031 Adding some fonts 2023-03-27 10:19:09 -06:00
38 changed files with 1012 additions and 129 deletions

60
colors.md Normal file
View File

@ -0,0 +1,60 @@
Colors
### Sunbaked Mint
HEX: #80e8d4
RGB: 128, 232, 212
CMYK: 43, 0, 25, 0
### Honey Dijon
HEX: #e2ae61
RGB: 226, 174, 97
CMYK: 1, 32, 72, 0
### Ultimate Gray
HEX: #97999b
RGB: 151, 153, 155
CMYK (approximation): 44, 35, 34, 1
### Frosty Blue
HEX: #bcddfc
RGB: 188, 221, 252
CMYK: 23, 5, 0, 0
### Electric Tangerine
HEX: #ff825c
RGB: 255, 130, 92
CMYK: 0, 61, 64, 0
### Holo Lilac
HEX: #c5d2fe
RGB: 197, 210, 254
CMYK: 22, 17, 0, 0
### Poppy Sunset
HEX: #ee645b
RGB: 238, 100, 91
CMYK: 2, 76, 62, 0
### Lime Nouveau
HEX: #cddf8b
RGB: 205, 223, 139
CMYK: 22, 1, 58, 5
### Very Peri
HEX: #6667ab
RGB: 102, 103, 171
CMYK (approximation): 40, 40, 0, 33
### Classic Blue
HEX: #0f4c81
RGB: 15, 76, 129
CMYK (approximation): 99, 76, 24, 8

View File

@ -39,8 +39,8 @@ REDIS_PASSWORD=null
REDIS_PORT=6379 REDIS_PORT=6379
MAIL_MAILER=smtp MAIL_MAILER=smtp
MAIL_HOST=mailhog MAIL_HOST=mailpit
MAIL_PORT=1125 MAIL_PORT=1025
MAIL_USERNAME=null MAIL_USERNAME=null
MAIL_PASSWORD=null MAIL_PASSWORD=null
MAIL_ENCRYPTION=null MAIL_ENCRYPTION=null
@ -74,8 +74,14 @@ AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID= PUSHER_APP_ID=
PUSHER_APP_KEY= PUSHER_APP_KEY=
PUSHER_APP_SECRET= PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1 PUSHER_APP_CLUSTER=mt1
VITE_SSL_KEY_FILE_PATH="/code/docker/configs/nginx/ssls/${APP_DOMAIN}/${APP_DOMAIN}.key"
VITE_SSL_CERT_FILE_PATH="/code/docker/configs/nginx/ssls/${APP_DOMAIN}/${APP_DOMAIN}.crt"
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
MIX_PUSHER_HOST="${PUSHER_HOST}" MIX_PUSHER_HOST="${PUSHER_HOST}"

View File

@ -1,17 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PSR2" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml"> <ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PSR2" xsi:noNamespaceSchemaLocation="vendor/slevomat/coding-standard">
<description>PHP Codesniffer ruleset for this project</description> <description>PHP Codesniffer ruleset for this project</description>
<file>./app/Models</file>
<file>./config</file>
<file>./database</file>
<file>./helpers</file>
<file>./lang</file>
<file>./resources/views</file>
<file>./routes</file>
<exclude-pattern>*/vendor/*</exclude-pattern>
<arg name="basepath" value="."/> <arg name="basepath" value="."/>
<arg name="parallel" value="4"/> <arg name="parallel" value="4"/>
<arg name="report" value="full"/> <arg name="report" value="full"/>
@ -24,6 +14,16 @@
<autoload>./vendor/autoload.php</autoload> <autoload>./vendor/autoload.php</autoload>
<file>./app/Models</file>
<file>./config</file>
<file>./database</file>
<file>./helpers</file>
<file>./lang</file>
<file>./resources/views</file>
<file>./routes</file>
<exclude-pattern>*/vendor/*</exclude-pattern>
<!-- Don't hide tokenizer exceptions --> <!-- Don't hide tokenizer exceptions -->
<rule ref="Internal.Tokenizer.Exception"> <rule ref="Internal.Tokenizer.Exception">
<type>error</type> <type>error</type>

View File

@ -0,0 +1,6 @@
Contact: mailto:person@domain.com
Contact: https://twitter.com/person
Expires: 2024-09-14T14:00:00.000Z
Encryption: https://keybase.io/person
Encryption: https://domain.com/pgp-key.txt
Preferred-Languages: en

30
src/SECURITY.md Normal file
View File

@ -0,0 +1,30 @@
<!-- AUTO-GENERATED, DO NOT EDIT! -->
<!-- Please edit the original at https://github.com/ory/meta/blob/master/templates/repository/common/SECURITY.md -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Security Policy](#security-policy)
- [Supported Versions](#supported-versions)
- [Reporting a Vulnerability](#reporting-a-vulnerability)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
# Security Policy
## Supported Versions
We release patches for security vulnerabilities. Which versions are eligible for
receiving such patches depends on the CVSS v3.0 Rating:
| CVSS v3.0 | Supported Versions |
| --------- | ----------------------------------------- |
| 9.0-10.0 | Releases within the previous three months |
| 4.0-8.9 | Most recent release |
## Reporting a Vulnerability
Please report (suspected) security vulnerabilities to
**[security@ory.sh](mailto:security@ory.sh)**. You will receive a response from
us within 48 hours. If the issue is confirmed, we will release a patch as soon
as possible depending on complexity but historically within a few days.

View File

@ -0,0 +1,28 @@
<?php
namespace App\Actions\Chained;
use App\Models\User;
use Closure;
class GenerateProfilePhoto
{
/**
* Generates a profile photo for a user and saves it
* to disk.
*
* @package App\Actions\Chained\GenerateProfilePhoto
* @since 1.0.0
*
* @param \App\Models\User $user
* @param \Closure $next
*
* @return \App\Models\User
*/
public function __invoke(User $user, Closure $next): User
{
//
return $next($user);
}
}

View File

@ -2,21 +2,14 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Inertia\Response; use Inertia\Response;
use Jenssegers\Agent\Agent;
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
use Laravel\Jetstream\Http\Controllers\Inertia\Concerns\ConfirmsTwoFactorAuthentication; use Laravel\Jetstream\Http\Controllers\Inertia\UserProfileController as JetstreamUserProfileController;
use Laravel\Jetstream\Jetstream; use Laravel\Jetstream\Jetstream;
class UserProfileController extends Controller class UserProfileController extends JetstreamUserProfileController
{ {
use ConfirmsTwoFactorAuthentication;
/** /**
* Show the general profile settings screen. * Show the general profile settings screen.
* *
@ -36,56 +29,4 @@ class UserProfileController extends Controller
'timezones' => timezone_identifiers_list(), 'timezones' => timezone_identifiers_list(),
]); ]);
} }
/**
* Get the current sessions.
*
* @since 1.0.0
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Support\Collection
*/
public function sessions(Request $request): Collection
{
if (config('session.driver') !== 'database') {
return collect();
}
return collect(
DB::connection(config('session.connection'))->table(config('session.table', 'sessions'))
->where('user_id', $request->user()->getAuthIdentifier())
->orderBy('last_activity', 'desc')
->get()
)->map(function ($session) use ($request) {
$agent = $this->createAgent($session);
return (object) [
'agent' => [
'is_desktop' => $agent->isDesktop(),
'platform' => $agent->platform(),
'browser' => $agent->browser(),
],
'ip_address' => $session->ip_address,
'is_current_device' => $session->id === $request->session()->getId(),
'last_active' => Carbon::createFromTimestamp($session->last_activity)->diffForHumans(),
];
});
}
/**
* Create a new agent instance from the given session.
*
* @since 1.0.0
*
* @param mixed $session
*
* @return \Jenssegers\Agent\Agent
*/
protected function createAgent($session): Agent
{
return tap(new Agent, function ($agent) use ($session) {
$agent->setUserAgent($session->user_agent);
});
}
} }

View File

@ -2,54 +2,50 @@
namespace App\Models\Traits; namespace App\Models\Traits;
use Illuminate\Database\Eloquent\Casts\Attribute;
trait FormattedPhoneTrait trait FormattedPhoneTrait
{ {
/** /**
* Format a phone number to be human readable. * Format a phone number to be human readable.
* *
* @since 1.0.0 * @package Namespace\App\Contact
* * @since 1.0.0
* @return string
*/
public function getPhoneNumberAttribute(): string
{
$phoneLength = strlen($this->phone);
$phoneNumber = preg_replace('//', '', $this->phone);
if ($phoneLength > 10) {
$countryCode = substr($phoneNumber, 0, $phoneLength - 10);
$areaCode = substr($phoneNumber, -10, 3);
$nextThree = substr($phoneNumber, -7, 3);
$lastFour = substr($phoneNumber, -4, 4);
$phoneNumber = "({$areaCode}) {$nextThree}-{$lastFour}";
} elseif ($phoneLength == 10) {
$areaCode = substr($phoneNumber, 0, 3);
$nextThree = substr($phoneNumber, 3, 3);
$lastFour = substr($phoneNumber, 6, 4);
$phoneNumber = "({$areaCode}) {$nextThree}-{$lastFour}";
} elseif ($phoneLength == 7) {
$nextThree = substr($phoneNumber, 0, 3);
$lastFour = substr($phoneNumber, 3, 4);
$phoneNumber = "{$nextThree}-{$lastFour}";
}
return $phoneNumber;
}
/**
* Remove all non-numeric characters from the phone number.
*
* @since 1.0.0
*
* @param string $value
* *
* @return void * @return void
*/ */
public function setPhoneNumberAttribute($value): void protected function phoneNumber(): Attribute
{ {
$this->attributes['phone'] = preg_replace('/[^0-9]/', '', $value); return Attribute::make(
get: function (mixed $value, array $attributes) {
$phoneLength = strlen($attributes['phone_number']);
$phoneNumber = preg_replace('/[^0-9]/', '', $attributes['phone_number']);
if ($phoneLength > 10) {
$countryCode = substr($phoneNumber, 0, $phoneLength - 10);
$areaCode = substr($phoneNumber, -10, 3);
$nextThree = substr($phoneNumber, -7, 3);
$lastFour = substr($phoneNumber, -4, 4);
$phoneNumber = "({$areaCode}) {$nextThree}-{$lastFour}";
} elseif ($phoneLength == 10) {
$areaCode = substr($phoneNumber, 0, 3);
$nextThree = substr($phoneNumber, 3, 3);
$lastFour = substr($phoneNumber, 6, 4);
$phoneNumber = "({$areaCode}) {$nextThree}-{$lastFour}";
} elseif ($phoneLength == 7) {
$nextThree = substr($phoneNumber, 0, 3);
$lastFour = substr($phoneNumber, 3, 4);
$phoneNumber = "{$nextThree}-{$lastFour}";
}
return $phoneNumber;
},
set: function (mixed $value) {
return preg_replace('/[^0-9]/', '', $value);
},
);
} }
} }

View File

@ -0,0 +1,88 @@
<?php
namespace Laravel\Jetstream;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
trait HasProfilePhoto
{
/**
* Update the user's profile photo.
*
* @param \Illuminate\Http\UploadedFile $photo
* @param string $storagePath
* @return void
*/
public function updateProfilePhoto(UploadedFile $photo, $storagePath = 'profile-photos')
{
tap($this->profile_photo_path, function ($previous) use ($photo, $storagePath) {
$this->forceFill([
'profile_photo_path' => $photo->storePublicly(
$storagePath, ['disk' => $this->profilePhotoDisk()]
),
])->save();
if ($previous) {
Storage::disk($this->profilePhotoDisk())->delete($previous);
}
});
}
/**
* Delete the user's profile photo.
*
* @return void
*/
public function deleteProfilePhoto()
{
if (! Features::managesProfilePhotos()) {
return;
}
if (is_null($this->profile_photo_path)) {
return;
}
Storage::disk($this->profilePhotoDisk())->delete($this->profile_photo_path);
$this->forceFill([
'profile_photo_path' => null,
])->save();
}
/**
* Get the URL to the user's profile photo.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function profilePhotoUrl(): Attribute
{
return Attribute::get(function () {
return $this->profile_photo_path
? Storage::disk($this->profilePhotoDisk())->url($this->profile_photo_path)
: $this->defaultProfilePhotoUrl();
});
}
/**
* Get the default profile photo URL if no profile photo has been uploaded.
*
* @return string
*/
protected function defaultProfilePhotoUrl()
{
return 'https://avatars.test/avatar?size=256';
}
/**
* Get the disk that profile photos should be stored on.
*
* @return string
*/
protected function profilePhotoDisk()
{
return isset($_ENV['VAPOR_ARTIFACT_NAME']) ? 's3' : config('jetstream.profile_photo_disk', 'public');
}
}

View File

@ -17,6 +17,9 @@
"spatie/laravel-permission": "", "spatie/laravel-permission": "",
"zizaco/entrust": "", "zizaco/entrust": "",
// Security stuff
"abuseipdb/laravel": "", // API to check an IP for abusive behavior with option to report IP for abusive behavior
// Options/Flags // Options/Flags
"spatie/laravel-model-flags": "", // add a simple true/false flag to any model "spatie/laravel-model-flags": "", // add a simple true/false flag to any model
@ -30,6 +33,9 @@
"torann/geoip": "", // support for multiple GeoIP services "torann/geoip": "", // support for multiple GeoIP services
"coderjerk/nasa-php": "", // NASA API integrations "coderjerk/nasa-php": "", // NASA API integrations
// File management
"czim/laravel-paperclip": "", // attach files to an Eloquent model
// Media (image/video/audio) Management // Media (image/video/audio) Management
"intervention/image": "", // image manipulation "intervention/image": "", // image manipulation
"intervention/imagecache": "", // caching for intervention/image "intervention/imagecache": "", // caching for intervention/image
@ -37,6 +43,7 @@
"spatie/laravel-image-optimizer": "", // optimize png, jpg, svg, and gif "spatie/laravel-image-optimizer": "", // optimize png, jpg, svg, and gif
"unisharp/laravel-filemanager": "", // File manager (including uploads) "unisharp/laravel-filemanager": "", // File manager (including uploads)
"pbmedia/laravel-ffmpeg": "", // Integration with FFMpeg "pbmedia/laravel-ffmpeg": "", // Integration with FFMpeg
"maestroerror/php-heic-to-jpg": "", // Use Go(?) to convert HEIC/HEIF to JPEG
// Localization // Localization
"mcamara/laravel-localization": "", // localization that also handles route translations "mcamara/laravel-localization": "", // localization that also handles route translations
@ -69,6 +76,7 @@
"protonemedia/laravel-verify-new-email": "", // must verify new email address before email update will be completed "protonemedia/laravel-verify-new-email": "", // must verify new email address before email update will be completed
"protonemedia/inertiajs-tables-laravel-query-builder": "", // datatables for InertiaJS/Vue and Laravel "protonemedia/inertiajs-tables-laravel-query-builder": "", // datatables for InertiaJS/Vue and Laravel
"ikechukwukalu/requirepin": "", // use password/pin protection for routes
"doctrine/dbal": "", // useful for artisan db:show "doctrine/dbal": "", // useful for artisan db:show
}, },

View File

@ -6,6 +6,7 @@ use App\Models\Language;
use App\Models\Team; use App\Models\Team;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Laravel\Jetstream\Features; use Laravel\Jetstream\Features;
@ -71,4 +72,25 @@ class UserFactory extends Factory
'ownedTeams' 'ownedTeams'
); );
} }
/**
* Indicate that the user should have an avatar image.
*
* @return $this
*/
public function withAvatar()
{
if (! Features::enabled(Features::profilePhotos())) {
return $this->state([]);
}
$imageUrl = 'https://avatars.test/';
$imageContents = file_get_contents($imageUrl);
$imageName = md5($imageContents) . '.jpg';
Storage::put("public/avatars/{$imageName}", $imageContents);
return $this->state([
'profile_photo_path' => "avatars/{$imageName}"
]);
}
} }

View File

@ -24,6 +24,7 @@ $httpCodes = [
204 => 'HTTP_NO_CONTENT', 204 => 'HTTP_NO_CONTENT',
205 => 'HTTP_RESET_CONTENT', 205 => 'HTTP_RESET_CONTENT',
206 => 'HTTP_PARTIAL_CONTENT', 206 => 'HTTP_PARTIAL_CONTENT',
218 => 'HTTP_THIS_IS_FINE', // Apache specific
// 300's (redirections / "go away") // 300's (redirections / "go away")
300 => 'HTTP_MULTIPLE_CHOICE', 300 => 'HTTP_MULTIPLE_CHOICE',
@ -57,12 +58,14 @@ $httpCodes = [
236 => 'HTTP_UPGRADE_REQUIRED', 236 => 'HTTP_UPGRADE_REQUIRED',
428 => 'HTTP_PRECONDITION_REQUIRED', 428 => 'HTTP_PRECONDITION_REQUIRED',
429 => 'HTTP_TOO_MANY_REQUESTS', 429 => 'HTTP_TOO_MANY_REQUESTS',
444 => 'HTTP_NO_RESPONSE', // Nginx specific, used internally to return no info and close connection immediately
451 => 'HTTP_GAG_ORDER', 451 => 'HTTP_GAG_ORDER',
// 500's (server-level problem, process died or configuration is incorrect / "server screwed up") // 500's (server-level problem, process died or configuration is incorrect / "server screwed up")
500 => 'HTTP_SERVER_ERROR', 500 => 'HTTP_SERVER_ERROR',
501 => 'HTTP_NOT_IMPLEMENTED', 501 => 'HTTP_NOT_IMPLEMENTED',
503 => 'HTTP_UNAVAILABLE', 503 => 'HTTP_UNAVAILABLE',
529 => 'HTTP_SITE_OVERLOADED', // Qualys specific, API response to indicate server resources are over capacity
530 => 'HTTP_SUSPENDED', 530 => 'HTTP_SUSPENDED',
]; ];

View File

@ -15,6 +15,47 @@ require_once "functions/temperatures.php";
| |
*/ */
if (! function_exists('clamp')) {
/**
* Ensure a numerical value is between two bounds.
*
* @since 1.0.0
*
* @param int|float|string $number The value to be clamped between two other values.
* @param int|float|string $minNumber The miminum value for clamping bounds.
* @param int|float|string $maxNumber The maximum value for clamping bounds.
*
* @throws \Exception
*
* @return int|float
*/
function clamp($number, $minNumber, $maxNumber)
{
if (! is_numeric($number)) {
throw new Exception('Clamp number must be numeric in value.');
}
if (! is_numeric($minNumber)) {
throw new Exception('Clamped minimum number must be numeric in value.');
}
if (! is_numeric($maxNumber)) {
throw new Exception('Clamped maximum number must be numeric in value.');
}
$returnValue = $number;
if ($minNumber >= $number) {
$returnValue = $minNumber;
}
if ($maxNumber <= $number) {
$returnValue = $maxNumber;
}
return $returnValue;
}
}
if (! function_exists('humanBytes')) { if (! function_exists('humanBytes')) {
/** /**
* Convert bytes to a human-friendly format. * Convert bytes to a human-friendly format.
@ -195,7 +236,7 @@ if (! function_exists('maybe_unserialize')) {
* *
* @param mixed $data * @param mixed $data
* *
* @return mixed * @return array|string|bool
*/ */
function maybe_unserialize($data) function maybe_unserialize($data)
{ {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -26,10 +26,54 @@
@import 'components/navbars.css'; @import 'components/navbars.css';
@import 'components/pagination.css'; @import 'components/pagination.css';
:root {
--primary-text-color: hsl(0, 90.4%, 59.2%);
--primary-text-color-gradient-start: hsl(270, 66.9%, 47.5%);
--primary-text-color-gradient-end: hsl(330, 100%, 50%);
--text-info-color: hsl(191, 82%, 50%);
--text-info-color-gradient-start: hsl(227, 100%, 56.5%);
--text-info-color-gradient-end: hsl(191, 98.2%, 56.1%);
--text-success-color: hsl(86, 81.4%, 46.3%);
--text-success-color-gradient-start: hsl(133, 76.5%, 38.4%);
--text-success-color-gradient-end: hsl(72, 81.1%, 52.4%);
--text-warning-color: hsl(47, 96.2%, 59.2%);
--text-warning-color-gradient-start: hsl(0, 90.4%, 59.2%);
--text-warning-color-gradient-end: hsl(47, 96.2%, 59.2%);
--text-danger-color: hsl(0, 95%, 47.1%);
--text-danger-color-gradient-start: hsl(0, 92.8%, 43.5%);
--text-danger-color-gradient-end: hsl(344, 100%, 70%);
}
@media (prefers-reduced-motion) {
*, *::before, *::after {
animation-duration: 0s !important;
/* additional recommendation */
transition: none !important;
scroll-behavior: auto !important;
}
}
body { body {
min-height: 100vh; background-image: linear-gradient(100deg, hsl(0, 0%, 98%), hsl(240, 5.9%, 90%));
color: hsl(240, 5.9%, 10%);
/*color: lch(8.35%, 2.25, 285.92);*/
-webkit-font-smoothing: antialiased;
min-height: 100dvh;
overflow: auto; overflow: auto;
scrollbar-gutter: stable both-edges; scrollbar-gutter: stable both-edges;
text-rendering: optimizeLegibility;
font-size: 1.25rem;
line-height: 1.1;
/* these will clamp the width between the two values
and keep it at 90% of the max when between them */
max-width: clamp(320px, 90%, 1280px);
margin: auto;
} }
html, body { html, body {
@ -46,6 +90,16 @@ nav {
user-select: none; user-select: none;
} }
img {
max-width: 100%;
height: auto;
vertical-align: middle;
font-style: italic;
background-repeat: no-repeat;
background-size: cover;
shape-margin: 0.75rem;
}
@media (max-width: 1023px) { @media (max-width: 1023px) {
.grid-container { .grid-container {
@apply grid-cols-1; @apply grid-cols-1;

View File

@ -0,0 +1,106 @@
.container {
display: grid;
gap: 4em 1em;
}
.primary-button {
--h: 196;
--s: 100%;
--l: 41%;
}
.secondary-button {
--h: 28;
--s: 100%;
--l: 41%;
}
.glass-button {
font-size: clamp(1.2rem, 5vw + 1rem, 2.5rem);
width: 10em;
height: 4em;
border-radius: 0.5em;
background-image: linear-gradient(#0003,#0000);
box-shadow:
0 -0.125em 0.25em #0002,
0 0.25em 0.25em hsl(var(--h) var(--s) var(--l) / 0.5),
0 0 0 0.1em hsl(var(--h) var(--s) var(--l) / 0.5),
0 0.175em 0.3em hsl(var(--h) var(--s) var(--l) / 0.5) inset,
0 -0.025em 0.175em hsl(var(--h) var(--s) var(--l) / 0.4) inset,
0 -0.25em 1em 0.3em hsl(var(--h) var(--s) var(--l) / 0.3) inset,
0 0.6em 0 hsl(var(--h) var(--s) var(--l) / 0.3) inset,
0 2em 1em #0004;
backdrop-filter: blur(0.15em);
position: relative;
display: grid;
place-content: center;
color: hsl(var(--h) var(--s) var(--l) / .7);
text-shadow:
0.03em 0.03em #fff5,
-0.03em -0.03em #0005;
cursor: pointer;
transition: 0.1s ease;
padding-top: 0.2em;
border: none;
background: transparent;
}
.glass-button:before {
content: '';
height: 1.5em;
left: 10%;
top: 100%;
position: absolute;
width: 80%;
}
.glass-button:after {
content: '';
inset: 0;
top: 0.5em;
position: absolute;
background-image:
linear-gradient(
105deg,
transparent 20%,
hsl(var(--h) var(--s) var(--l) / .2) 20%,
hsl(var(--h) var(--s) var(--l) / .2) 30%,
transparent 30%,
transparent 32%,
hsl(var(--h) var(--s) var(--l) / .2) 5%,
hsl(var(--h) var(--s) var(--l) / .2) 40%,
transparent 0%
);
background-size: 400% 100%;
background-position: 100% 0%;
transition: .3s ease;
}
.glass-button:active:after {
background-position: -50% 0%;
}
.glass-button:active {
backdrop-filter: blur(0.08em);
box-shadow:
0 -0.125em 0.25em #0002,
0 0.25em 0.25em hsl(var(--h) var(--s) var(--l) / 0.5),
0 0 0 0.1em hsl(var(--h) var(--s) var(--l) / 0.5),
0 0.175em 0.3em hsl(var(--h) var(--s) var(--l) / 0.8) inset,
0 -0.025em 0.175em hsl(var(--h) var(--s) var(--l) / 0.4) inset,
0 -0.25em 1em 0.3em hsl(var(--h) var(--s) var(--l) / 0.3) inset,
0 0.6em 0 hsl(var(--h) var(--s) var(--l) / 0.3) inset,
0 1em 0.5em #0004;
translate: .01em .25em;
}
.glass-button:active:before {
height: 1em;
}
/*body {
background-color: #3d3d3d;
display: grid;
margin: 0;
min-height: 100vh;
place-content: center;
}*/

View File

@ -3,6 +3,70 @@
/** +--------------------------------+ **/ /** +--------------------------------+ **/
@font-face { @font-face {
font-family: "BarlowCondensed";
font-weight: 400;
font-style: normal;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-Regular.woff2") format("woff2");
}
@font-face {
font-family: "BarlowCondensed";
font-weight: 400;
font-style: italic;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-Italic.woff2") format("woff2");
}
@font-face {
font-family: "BarlowCondensed";
font-weight: 500;
font-style: normal;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-Medium.woff2") format("woff2");
}
@font-face {
font-family: "BarlowCondensed";
font-weight: 500;
font-style: italic;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-MediumItalic.woff2") format("woff2");
}
@font-face {
font-family: "BarlowCondensed";
font-weight: 600;
font-style: normal;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-SemiBold.woff2") format("woff2");
}
@font-face {
font-family: "BarlowCondensed";
font-weight: 600;
font-style: italic;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-SemiBoldItalic.woff2") format("woff2");
}
@font-face {
font-family: "BarlowCondensed";
font-weight: 700;
font-style: normal;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-Bold.woff2") format("woff2");
}
@font-face {
font-family: "BarlowCondensed";
font-weight: 700;
font-style: italic;
font-display: swap;
src: url("/fonts/BarlowCondensed/BarlowCondensed-BoldItalic.woff2") format("woff2");
}
/*@font-face {
font-family: "Lato"; font-family: "Lato";
src: url('/fonts/Lato/Lato-Regular.woff2') format("woff2"); src: url('/fonts/Lato/Lato-Regular.woff2') format("woff2");
font-weight: 400; font-weight: 400;
@ -48,13 +112,77 @@
font-weight: 700; font-weight: 700;
font-style: italic; font-style: italic;
font-display: swap; font-display: swap;
} }*/
/** +--------------------------------+ **/ /** +--------------------------------+ **/
/** | Serif fonts | **/ /** | Serif fonts | **/
/** +--------------------------------+ **/ /** +--------------------------------+ **/
@font-face { @font-face {
font-family: "Montserrat";
font-weight: 400;
font-style: normal;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-Regular.woff2") format("woff2");
}
@font-face {
font-family: "Montserrat";
font-weight: 400;
font-style: italic;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-Italic.woff2") format("woff2");
}
@font-face {
font-family: "Montserrat";
font-weight: 500;
font-style: normal;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-Medium.woff2") format("woff2");
}
@font-face {
font-family: "Montserrat";
font-weight: 500;
font-style: italic;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-MediumItalic.woff2") format("woff2");
}
@font-face {
font-family: "Montserrat";
font-weight: 600;
font-style: normal;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-SemiBold.woff2") format("woff2");
}
@font-face {
font-family: "Montserrat";
font-weight: 600;
font-style: italic;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-SemiBoldItalic.woff2") format("woff2");
}
@font-face {
font-family: "Montserrat";
font-weight: 700;
font-style: normal;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-Bold.woff2") format("woff2");
}
@font-face {
font-family: "Montserrat";
font-weight: 700;
font-style: italic;
font-display: swap;
src: url("/fonts/Montserrat/Montserrat-BoldItalic.woff2") format("woff2");
}
/*@font-face {
font-family: "Nunito"; font-family: "Nunito";
src: url('/fonts/Nunito/Nunito-Regular.woff2') format("woff2"); src: url('/fonts/Nunito/Nunito-Regular.woff2') format("woff2");
font-weight: 400; font-weight: 400;
@ -118,7 +246,7 @@
font-stretch: 75% 125%; font-stretch: 75% 125%;
font-style: italic; font-style: italic;
font-display: swap; font-display: swap;
} }*/
/*@font-face { /*@font-face {
font-family: "Raleway"; font-family: "Raleway";

View File

@ -0,0 +1,45 @@
.text-gradient {
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
position: relative;
z-index: 1;
}
.text-gradient.text-primary {
background-image: linear-gradient(310deg, var(--primary-text-color-gradient-start), var(--primary-text-color-gradient-end));
}
.text-primary {
color: var(--primary-text-color);
}
.text-gradient.text-info {
background-image: linear-gradient(310deg, var(--text-info-color-gradient-start), var(--text-info-color-gradient-end));
}
.text-info {
color: var(--text-info-color);
}
.text-gradient.text-success {
background-image: linear-gradient(310deg, var(--text-success-color-gradient-start), var(--text-success-color-gradient-end));
color: hsl(86, 81.4%, 46.3%);
}
.text-success {
color: var(--text-success-color);
}
.text-gradient.text-warning {
background-image: linear-gradient(310deg, var(--text-warning-color-gradient-start), var(--text-warning-color-gradient-end));
color: hsl(47, 96.2%, 59.2%);
}
.text-warning {
color: var(--text-warning-color);
}
.text-gradient.text-danger {
background-image: linear-gradient(310deg, var(--text-danger-color-gradient-start), var(--text-danger-color-gradient-end));
color: hsl(0, 95%, 47.1%);
}
.text-danger {
color: var(--text-danger-color);
}

View File

@ -1,3 +1,30 @@
.button-row { .button-row {
@apply inline-grid grid-flow-col auto-cols-max items-center; /* intentionally leaving gap out so that it can be set on per-case basis */ @apply inline-grid grid-flow-col auto-cols-max items-center; /* intentionally leaving gap out so that it can be set on per-case basis */
} }
.gradBorder i {
content: '';
position: absolute;
z-index: -1;
inset: 0;
border-radius: 30px;
padding: 1.5px; /* the thickness of the border */
/* the below will do the magic */
mask:
linear-gradient(#fff 0 0) content-box,
/* this will cover only the content area (no padding) */
linear-gradient(#fff 0 0); /* this will cover all the area */
-webkit-mask-composite: xor; /* needed for old browsers until the below is more supported */
mask-composite: exclude; /* this will exclude the first layer from the second so only the padding area will be kept visible */
}
.gradBorder i::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: linear-gradient(180deg, #ffffff73 0%, #ffffff10 50%);
transition: transform 0.7s linear;
}

View File

@ -1,3 +1,108 @@
:root { :root {
/**/
/** ------------------------------
* START -- https://coolors.co/022f40-38aecc-0090c1-183446-046e8f
* -------------------------------**/
/* CSS HEX */
--prussian-blue: #022f40ff;
--pacific-cyan: #38aeccff;
--blue-ncs: #0090c1ff;
--prussian-blue-2: #183446ff;
--cerulean: #046e8fff;
/* CSS HSL */
--prussian-blue: hsla(196, 94%, 13%, 1);
--pacific-cyan: hsla(192, 59%, 51%, 1);
--blue-ncs: hsla(195, 100%, 38%, 1);
--prussian-blue-2: hsla(203, 49%, 18%, 1);
--cerulean: hsla(194, 95%, 29%, 1);
/* SCSS HEX */
$prussian-blue: #022f40ff;
$pacific-cyan: #38aeccff;
$blue-ncs: #0090c1ff;
$prussian-blue-2: #183446ff;
$cerulean: #046e8fff;
/* SCSS HSL */
$prussian-blue: hsla(196, 94%, 13%, 1);
$pacific-cyan: hsla(192, 59%, 51%, 1);
$blue-ncs: hsla(195, 100%, 38%, 1);
$prussian-blue-2: hsla(203, 49%, 18%, 1);
$cerulean: hsla(194, 95%, 29%, 1);
/* SCSS RGB */
$prussian-blue: rgba(2, 47, 64, 1);
$pacific-cyan: rgba(56, 174, 204, 1);
$blue-ncs: rgba(0, 144, 193, 1);
$prussian-blue-2: rgba(24, 52, 70, 1);
$cerulean: rgba(4, 110, 143, 1);
/* SCSS Gradient */
/*$gradient-top: linear-gradient(0deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-right: linear-gradient(90deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-bottom: linear-gradient(180deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-left: linear-gradient(270deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-top-right: linear-gradient(45deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-bottom-right: linear-gradient(135deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-top-left: linear-gradient(225deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-bottom-left: linear-gradient(315deg, #022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/*$gradient-radial: radial-gradient(#022f40ff, #38aeccff, #0090c1ff, #183446ff, #046e8fff);*/
/** ------------------------------
* END -- https://coolors.co/022f40-38aecc-0090c1-183446-046e8f
* -------------------------------**/
/** ------------------------------
* START -- https://coolors.co/8ac482-47783f-ffbe86-ffb5c2-3777ff
* -------------------------------**/
/* CSS HEX */
--pistachio: #8ac482ff;
--fern-green: #47783fff;
--peach: #ffbe86ff;
--cherry-blossom-pink: #ffb5c2ff;
--blue-crayola: #3777ffff;
/* CSS HSL */
--pistachio: hsla(113, 36%, 64%, 1);
--fern-green: hsla(112, 31%, 36%, 1);
--peach: hsla(28, 100%, 76%, 1);
--cherry-blossom-pink: hsla(349, 100%, 85%, 1);
--blue-crayola: hsla(221, 100%, 61%, 1);
/* SCSS HEX */
$pistachio: #8ac482ff;
$fern-green: #47783fff;
$peach: #ffbe86ff;
$cherry-blossom-pink: #ffb5c2ff;
$blue-crayola: #3777ffff;
/* SCSS HSL */
$pistachio: hsla(113, 36%, 64%, 1);
$fern-green: hsla(112, 31%, 36%, 1);
$peach: hsla(28, 100%, 76%, 1);
$cherry-blossom-pink: hsla(349, 100%, 85%, 1);
$blue-crayola: hsla(221, 100%, 61%, 1);
/* SCSS RGB */
$pistachio: rgba(138, 196, 130, 1);
$fern-green: rgba(71, 120, 63, 1);
$peach: rgba(255, 190, 134, 1);
$cherry-blossom-pink: rgba(255, 181, 194, 1);
$blue-crayola: rgba(55, 119, 255, 1);
/* SCSS Gradient */
/*$gradient-top: linear-gradient(0deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-right: linear-gradient(90deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-bottom: linear-gradient(180deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-left: linear-gradient(270deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-top-right: linear-gradient(45deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-bottom-right: linear-gradient(135deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-top-left: linear-gradient(225deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-bottom-left: linear-gradient(315deg, #8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/*$gradient-radial: radial-gradient(#8ac482ff, #47783fff, #ffbe86ff, #ffb5c2ff, #3777ffff);*/
/** ------------------------------
* END -- https://coolors.co/8ac482-47783f-ffbe86-ffb5c2-3777ff
* -------------------------------**/
} }

View File

@ -19,6 +19,14 @@ module.exports = {
extend: { extend: {
colors: { colors: {
'sherwin': {
'marshmallow': '#eee9e0'
'ice-cube': '#e3e4e1',
'peppercorn': '#585858',
'black-magic': '#323132',
'tricorn-black': '#2f2f30',
},
// use https://uicolors.app/create // use https://uicolors.app/create
// neutals // neutals
'nomad': { 'nomad': {
@ -35,6 +43,19 @@ module.exports = {
}, },
// reds // reds
'crimson': {
50: '#fff1f1',
100: '#ffe0e0',
200: '#ffc6c6',
300: '#ff9e9e',
400: '#ff6666',
500: '#fd3636',
600: '#eb1717',
700: '#c60f0f',
800: '#a31111',
900: '#871515',
},
'monza': { 'monza': {
50: '#fff0f0', 50: '#fff0f0',
100: '#ffdede', 100: '#ffdede',
@ -74,6 +95,19 @@ module.exports = {
900: '#811a39', 900: '#811a39',
}, },
'violet-red': {
50: '#fff1f3',
100: '#ffe3e8',
200: '#ffccd7',
300: '#ffa2b6',
400: '#ff6d8f',
500: '#f94373',
600: '#e61858',
700: '#c20e4b',
800: '#a30e45',
900: '#8b1041',
},
// oranges // oranges
'saffron-mango': { 'saffron-mango': {
@ -102,8 +136,48 @@ module.exports = {
900: '#7a250d', 900: '#7a250d',
}, },
'hot-cinnamon': {
50: '#fdf8ed',
100: '#f9eacc',
200: '#f3d394',
300: '#edb75c',
400: '#e89e37',
500: '#e17e1f',
600: '#d3631a',
700: '#a54118',
800: '#86341a',
900: '#6f2c18',
},
'fire-bush': {
50: '#fef7ec',
100: '#faeacb',
200: '#f5d292',
300: '#efb65a',
400: '#ea9727',
500: '#e47d1c',
600: '#ca5b15',
700: '#a74016',
800: '#883218',
900: '#702a17',
},
// yellows // yellows
'vesuvius': {
50: '#fffbeb',
100: '#fef3c7',
200: '#fde58a',
300: '#fbd24e',
400: '#fabe25',
500: '#f49d0c',
600: '#d87607',
700: '#bc560a',
800: '#923f0e',
900: '#78340f',
},
'mango-tango': { 'mango-tango': {
50: '#fefbe8', 50: '#fefbe8',
100: '#fff6c2', 100: '#fff6c2',
@ -236,6 +310,19 @@ module.exports = {
900: '#163e2f', 900: '#163e2f',
}, },
'caribbean-green': {
50: '#effef9',
100: '#cafdef',
200: '#94fbe0',
300: '#57f1cf',
400: '#24ddba',
500: '#0ccaa9',
600: '#069b84',
700: '#0a7b6c',
800: '#0d6257',
900: '#105149',
},
// teals // teals
'aquamarine': { 'aquamarine': {
@ -357,6 +444,20 @@ module.exports = {
900: '#193961', 900: '#193961',
}, },
'azure-radiance': {
50: '#edfaff',
100: '#d6f2ff',
200: '#b5eaff',
300: '#83dfff',
400: '#48cbff',
500: '#1eacff',
600: '#068eff',
700: '#007aff',
800: '#085dc5',
900: '#0d519b',
},
// purples // purples
'lilac-bush': { 'lilac-bush': {
50: '#f8f5fd', 50: '#f8f5fd',
@ -397,6 +498,45 @@ module.exports = {
900: '#4b05ad', 900: '#4b05ad',
}, },
'medium-purple': {
50: '#f0f1fd',
100: '#e3e5fc',
200: '#cccdf9',
300: '#adadf4',
400: '#948ced',
500: '#8170e4',
600: '#7558d7',
700: '#6346bc',
800: '#503b98',
900: '#443679',
},
'wisteria': {
50: '#faf7fc',
100: '#f4eef9',
200: '#eaddf1',
300: '#dbc1e6',
400: '#c69dd5',
500: '#ac75c0',
600: '#965ca9',
700: '#774586',
800: '#633a6e',
900: '#54335c',
},
'amethyst': {
50: '#fcf5fe',
100: '#f7e9fe',
200: '#efd3fb',
300: '#e6b0f7',
400: '#d880f2',
500: '#c450e5',
600: '#b543d2',
700: '#8f25a6',
800: '#762088',
900: '#631f70',
},
'seance': { 'seance': {
50: '#fcf3ff', 50: '#fcf3ff',
100: '#fae7ff', 100: '#fae7ff',
@ -464,6 +604,19 @@ module.exports = {
900: '#8c0f45', 900: '#8c0f45',
}, },
'sea-pink': {
50: '#fdf3f4',
100: '#fbe8eb',
200: '#f6d5da',
300: '#ea9daa',
400: '#e58799',
500: '#d75c77',
600: '#c13d60',
700: '#a22e4f',
800: '#882947',
900: '#752642',
},
}, },

39
src/vite-ssr.config.js Normal file
View File

@ -0,0 +1,39 @@
import fs from 'fs';
import { defineConfig, loadEnv } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default ({ mode }) => {
process.env = Object.assign(process.env, loadEnv(mode, process.cwd(), ''));
return defineConfig({
build: {
reportCompressedSize: true,
},
plugins: [
laravel({
input: 'resources/js/app.js',
ssr: 'resources/js/ssr.js',
refresh: true,
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
ssr: {
noExternal: ['@inertiajs/server'],
},
server: {
host: process.env.APP_DOMAIN,
https: {
key: fs.readFileSync(`${process.env.VITE_SSL_KEY_FILE_PATH}`),
cert: fs.readFileSync(`${process.env.VITE_SSL_CERT_FILE_PATH}`),
},
},
});
}

View File

@ -10,6 +10,13 @@ export default ({ mode }) => {
build: { build: {
reportCompressedSize: true, reportCompressedSize: true,
}, },
server: {
host: process.env.APP_DOMAIN,
https: {
key: fs.readFileSync(`${process.env.VITE_SSL_KEY_FILE_PATH}`),
cert: fs.readFileSync(`${process.env.VITE_SSL_CERT_FILE_PATH}`),
},
},
plugins: [ plugins: [
laravel({ laravel({
input: 'resources/js/app.js', input: 'resources/js/app.js',
@ -25,15 +32,5 @@ export default ({ mode }) => {
}, },
}), }),
], ],
ssr: {
noExternal: ['@inertiajs/server'],
},
server: {
host: process.env.APP_DOMAIN,
https: {
key: fs.readFileSync(`/code/docker/configs/nginx/ssls/${process.env.APP_DOMAIN}/${process.env.APP_DOMAIN}.key`),
cert: fs.readFileSync(`/code/docker/configs/nginx/ssls/${process.env.APP_DOMAIN}/${process.env.APP_DOMAIN}.crt`),
},
},
}); });
} }