oDinZu
1 year ago
41 changed files with 4735 additions and 280 deletions
@ -0,0 +1,4 @@
|
||||
--- |
||||
# Only the main Sass file needs front matter (the dashes are enough) |
||||
--- |
||||
@import "styles" |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 65 KiB |
File diff suppressed because one or more lines are too long
@ -1 +1,4 @@
|
||||
{% comment %} |
||||
A back-to-top button that needs javascript. |
||||
{% endcomment %} |
||||
<button onclick="topFunction()" id="myBtn" title="Go to top">Top</button> |
||||
|
@ -1,22 +1,15 @@
|
||||
<!-- Footer --> |
||||
<footer id="footer"> |
||||
<ul class="alt-icons"> |
||||
<li><a href="{{ site.data.social.twitter_link }}" class="icon brands fa-twitter" target="_blank"><span class="label">Twitter</span></a></li> |
||||
<li><a href="{{ site.data.social.facebook_link }}" class="icon brands fa-facebook-f" target="_blank"><span class="label">Facebook</span></a></li> |
||||
<li><a href="{{ site.data.social.github_link }}" class="icon brands fa-github" target="_blank"><span class="label">GitHub</span></a></li> |
||||
<li><link rel="alternate" type="application/rss+xml" href="{{ site.data.social.rss_link }}" class="icon solid fa-rss" target="_blank"></li> |
||||
<li><a href="mailto:{{ site.data.global.info_email }}" class="icon solid fa-envelope" target="_blank"><span class="label">Email</span></a></li> |
||||
</ul> |
||||
<p class="copyright"> |
||||
© 2013-<script>document.write(new Date().getFullYear())</script> {{ site.data.global.legal_title }} <a href="{{ site.data.global.creator_link }}" target="_blank"></a><br /> |
||||
Donations are happily accepted with Love 💓! |
||||
<a href="https://opencollective.com/sharpetronics"><h3>Open Collective</h3></a> |
||||
</p> |
||||
<p class="copyright"> |
||||
© 2013-<script>document.write(new Date().getFullYear())</script> {{ site.data.global.legal_title }} <br /> |
||||
<a href="/humans.txt" target="_blank">Imagined by humans</a>, <a href="https://jekyllrb.com/" target="_blank">built with Jekyll</a>, |
||||
<a href="https://git.sharpetronics.com/SharpeTronics/sharpetronics.com" target="_blank">hosted by {{ site.data.global.legal_title }}</a><br /> |
||||
<a href="https://sharpetronics.com" target="_blank">hosted by {{ site.data.global.legal_title }}</a><br /> |
||||
<!-- Creative Commons Attribution-NoDerivs 3.0 United States License --> |
||||
{{ site.data.global.license_shorthand }} |
||||
</p> |
||||
<ul class="menu"> |
||||
<li><a href="{{ site.data.global.terms_link }}">Terms of Use</a></li> |
||||
<li><a href="{{ site.data.global.privacy_link }}">Privacy Policy</a></li> |
||||
<li><a href="{{ site.data.global.sitemap_link }}">Sitemap</a></li> |
||||
</ul> |
||||
</footer> |
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
--- |
||||
layout: posts |
||||
title: Journal |
||||
sub_title: A collection of articles about technology. |
||||
permalink: /blog |
||||
pagination: |
||||
enabled: true |
||||
collection: posts |
||||
--- |
@ -0,0 +1,15 @@
|
||||
--- |
||||
updatedAt: 2022-12-04T20:00:31.460Z |
||||
layout: post |
||||
title: SharpeTronics LLC Becomes Official |
||||
subheading: Winding Roads |
||||
slug: sharpe-tronics-llc-becomes-official |
||||
date: 2022-05-23 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/pillars_face_art_973bf824dd.webp |
||||
banner_image_description: An unbreakable pillar with a head holding up the ceiling. |
||||
category: Company |
||||
tags: Contribute, Technology, |
||||
--- |
||||
<p>We as in SharpeTronics LLC are proud to announce our business is official with the mountain state of West Virginia on March 17, 2021. </p><p>We also have our very own mailbox provided by the beloved Postmaster. </p><p>Furthermore, we now have pillars in place to begin building and creating avenues with our community. </p><blockquote><p>“The past is written, but the future is left for us to write.” —Star Trek</p></blockquote><p> </p> |
@ -0,0 +1,15 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T02:53:07.443Z |
||||
layout: post |
||||
title: Welcome To An Appalachian Technology Company |
||||
subheading: Where light travels at high altitudes. |
||||
slug: welcome-to-an-appalachian-technology-company |
||||
date: 2022-05-23 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/wv_seneca_rocks_sky_0d5928baa9.webp |
||||
banner_image_description: An image of the Sky in West Virginia. |
||||
category: Company |
||||
tags: Celebration, Linux, Open Source, Technology, |
||||
--- |
||||
<p>Welcome to SharpeTronics, where light travels at high altitudes. We are a mountain made company in the Appalachians of West Virginia that strives with software and hardware technologies. We are statewide leaders in our area of expertise and invite you to support local business. </p><p>Our mission is to enable a modern web architecture that empowers the user and enables accessibility for both beginners and experts. We are a technology business that challenges the status quo of web development and shares technical knowledge for both local and remote stations. </p><p>Our commitment to you is quality satisfaction, affordable and lightweight performance for worldwide availability with no strings attached. </p><p>We provide solutions that create resilient, secure and portable online infrastructure built to last the future, while enabling straight-forward seamless integration's for happy developers and editors alike. </p><p>We say NO to the complex insecurities and inaccessible culture created around hefty JavaScript frameworks like Angular, React or heavy database integration's like WordPress or Joomla. These structures create more resistance than needed and end up crafting solutions that are complicated, costly and unfriendly. </p><p> Our web stack delivers headless content management, worldwide availability, resiliency, accessibility and scalability, while maintaining simplicity, affordability and lightning performance. We remove unneeded barriers and strengthen connections between the user and developer. </p><p>A variety of keywords that are associated with our software stack include: JAMstack, progressive web apps (PWA), content management systems (CMS), Ecommerce, newsletters and static websites. If you are eager to learn, get in touch or join our team, please contact us via email.</p> |
@ -0,0 +1,35 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T23:11:32.639Z |
||||
layout: post |
||||
title: Configure a Static Qt5 from Source on Ubuntu 18.04 with X11 Support |
||||
subheading: Compiling & Configuring Qt from Source |
||||
slug: configure-a-static-qt5-from-source-on-ubuntu-18-04-with-x11-support |
||||
date: 2022-05-24 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/quantum_qt5_41fa19c935.webp |
||||
banner_image_description: A golden circuit board. |
||||
category: Devops |
||||
tags: Linux, Qt5, ARM64, Raspberry Pi 400, X11, |
||||
--- |
||||
<h3>Configure, Build, Install & Setup Qt 5.15.2 Source on Ubuntu 18.04 with X11 Support</h3><p>This tutorial will teach you how to compile from source via CLI (command-line interface) and enable customization for building Qt5 apps on different operating systems andor hardware architectures like RPI400.</p><p>When compiling Qt5 yourself, you are empowered with a configuration that is constant throughout the Linux Universe. This process is also very similar with compiling Qt apps on your (AArch64) ARM64 devices like RPi 400, Rock64 & PineBook64.</p><p><i>Note: This tutorial doesn’t include json Qtwebengine</i></p><h3>What is Qt?</h3><p>“Qt is a cross-platform application development framework for desktop, embedded and mobile.” [Qt Wiki]</p><h3>What is a Static Qt?</h3><p>In general, a static Qt option includes libraries locally. This aids in having an application run on different versions of Linux distros. When the application is compiled, we check the app with <i>ldd yourapp</i> to list what the binary is dependent on to run. Essentially, the Qt libraries are included in the binary. Decovar.dev has a great explanation on advantages and disadvantages of building a static Qt. [At last, let’s build Qt statically]</p><h3>Let’s Begin!</h3><h4>Remove & purge all Qt packages</h4><pre><code class="language-plaintext">sudo apt -y remove qt5* libqt5* qtcreator && sudo autoremove |
||||
</code></pre><h4>Download Qt 5.15.2 Source to qt5-sources folder</h4><pre><code class="language-plaintext">mkdir qt5-sources && cd qt5-sources && mkdir build-shadow |
||||
|
||||
wget https://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz |
||||
</code></pre><p>Verify MD5 hash</p><pre><code class="language-plaintext">md5sum qt-everywhere-src-5.15.2.tar.xz |
||||
</code></pre><pre><code class="language-plaintext">e1447db4f06c841d8947f0a6ce83a7b5 qt-everywhere-src-5.15.2.tar.xz |
||||
</code></pre><p>Un-tar Qt5 archive</p><pre><code class="language-plaintext">tar xf qt-everywhere-src-5.15.2.tar.xz |
||||
</code></pre><p>Move into build-shadow directory to configure your Qt 5.15.2</p><pre><code class="language-plaintext">cd build-shadow |
||||
</code></pre><h4>Install Qt5 Minimal Dependencies</h4><pre><code class="language-plaintext">sudo apt update |
||||
|
||||
sudo apt install build-essential libfontconfig1-dev libdbus-1-dev libfreetype6-dev libicu-dev libinput-dev libxkbcommon-dev libsqlite3-dev libssl-dev libpng-dev libjpeg-dev libglib2.0-dev |
||||
</code></pre><p>(Optional) Install VC4 Drivers for RPi 4 type devices (i.e. cortex-a53 & cortex-a72)</p><pre><code class="language-plaintext">sudo apt install libgles2-mesa-dev libgbm-dev libdrm-dev |
||||
</code></pre><h4>(Optional) Install X11 Support Dependencies</h4><pre><code class="language-plaintext">sudo apt install libx11-dev libxcb1-dev libxext-dev libxi-dev libxcomposite-dev libxcursor-dev libxtst-dev libxrandr-dev libfontconfig1-dev libfreetype6-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util0-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev</code></pre><h4>Configure Qt 5.15.2</h4><pre><code class="language-plaintext">../qt-everywhere-src-5.15.2/configure -static -release -openssl-linked -opensource -confirm-license -qt-zlib -qt-libpng -bundled-xcb-xinput \ |
||||
-skip qtlocation -skip qtmacextras -skip qtpurchasing -skip qtscript -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtdatavis3d -skip qtdoc -skip qtcharts -skip qtdeclarative -skip qt3d -skip qtwebengine -skip qtandroidextras -skip qtwebview -skip qtgamepad -skip qtquickcontrols -skip qtquickcontrols2 -skip qtremoteobjects -skip qtwebview -skip qtwebchannel -skip qtwebglplugin \ |
||||
-nomake examples -nomake tests -feature-fontconfig -no-feature-getentropy -v</code></pre><p>*If you would like to see a full list of options, we can do <strong>../qt-everywhere-src-5.15.2/configure -h</strong></p><p>Make the configuration <i>(-j 4 is number of cpus you want to use)</i></p><pre><code class="language-plaintext">make -j 4 |
||||
</code></pre><p>Install Qt5 into: <i>(default) /usr/local/</i></p><pre><code class="language-plaintext">sudo make install</code></pre><p><i>Note: Check and make sure ./configure has required deps; if you installed the deps, but still receiving errors, remove config.cache and ./configure again.</i></p><p><strong>Tip:</strong> <i>If you want to view your configuration summary, you may do so via nano config.summary from build-shadow directory</i></p><h4>Update profile to know where Qt5.15.2 bins are</h4><pre><code class="language-plaintext">nano ~/.bashrc</code></pre><p>Add this at the bottom of your .bashrc file.</p><pre><code class="language-plaintext"># set PATH for Qt 5.15.2 |
||||
export PATH="/usr/local/Qt-5.15.2/bin:$PATH"</code></pre><p>Reload your ~/.bashrc file & create new shell window.</p><pre><code class="language-plaintext">source ~/.bashrc |
||||
CTRL+SHIFT+T |
||||
ALT+1 |
||||
exit</code></pre><p>Verify Qt 5.15.2 has been installed</p><pre><code class="language-plaintext">qmake --version</code></pre><pre><code class="language-plaintext">QMake version 3.1 |
||||
Using Qt version 5.15.2 in /usr/local/Qt-5.15.2/lib</code></pre><h4>Build your happy Qt5 app</h4><pre><code class="language-plaintext">./build.sh</code></pre><h4>Support & Questions</h4><p><a href="https://github.com/SharpeTronics/sharpetronics.github.io/issues">sharpetronics.github</a></p><p><img class="image_resized" style="width:37.38%;" src="https://dash.sharpetronics.com/uploads/bob_ross_happy_59f18e7ebe.gif" alt="bob-ross-happy.gif"></p><h4>References</h4><p><a href="https://www.tal.org/tutorials/building-qt-515-raspberry-pi">tal.org/rpi</a></p><p><a href="https://doc.qt.io/qt-5/qtmodules.html">doc.qt.io/qtmodules</a></p><p><a href="https://wiki.qt.io/About_Qt">wiki.qt.io/about</a></p><p><a href="https://decovar.dev/blog/2018/02/17/build-qt-statically/#why-build-qt-statically">why-build-qt-statically</a></p> |
@ -0,0 +1,31 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T21:46:14.158Z |
||||
layout: post |
||||
title: Linux VPS Hardening |
||||
subheading: Initializing a secure environment |
||||
slug: linux-vps-hardening |
||||
date: 2022-05-24 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/linux_admin_0def8999f2.webp |
||||
banner_image_description: The back of a black hoodie hacking at software |
||||
category: Devops |
||||
tags: Linux, VPS, SSL, Security, |
||||
--- |
||||
<h3>Planting Seeds</h3><p>Administration of a virtual private Linux server (VPS) without a GUI cpanel is the only way to go. Going through any graphical user interface (GUI) to run critical services for your company is like playing the telephone game. Securing our environment begins at the terminal & from terminal experience we create a deeper learning experience for ourselves and build confidence along the way.</p><p>This article will extrapolate on initializing a Ubuntu Linux VPS for the first time and how we secure our environment through the terminal. No Windows or MacOS pancakes here; only Linux. When beginning a new server or garden, the soil is most important; we create an environment to protect and maximize growth potential. The VPS provider may give you an OS they installed, but I always create a fresh install myself.</p><h3>Logging in via SSH</h3><h4>Creating RSA Public Key </h4><p>Before you are able to login with SSH, you will most likely have to generate and add a RSA public key.</p><pre><code class="language-plaintext">ssh-keygen -t rsa -b 4096 </code></pre><h4>Copy / Paste Public Key</h4><p>After key is generated, we display the public key and add it to VPS account. <i>Optionally, you may have to add the key with ssh-copy-id user@ip_address.</i></p><pre><code class="language-plaintext">cat ~/.ssh/id_rsa.pub</code></pre><pre><code class="language-plaintext">ssh-rsa AAAEXAMPLECAQDBn0Z88lqrtya0Nd7yYtP/1o90vwVxjvCm/txb+SW85JRRnrI616d2iWwtVCSiUX0s59FfIPxUJl6vPqmxY40DIrX9KZijVpaq/TzWXh2ktCTjT6uBNMBRz/2lxP3w2AZov65dygjW5eQT9K9YB13dr1B4RkQMmUW5xiFbdHM0WzBYM2CMtE+lnmebn7m+B3DcvNkuGdT9Qw1/J24dTuNJSzJXVxzTOTlnVKOVSp1NWzu0USFI6dkrz8YImSgP9hQX970zTnzQ1Ctei4xlR/IiCpVGG6zWeV4oT3sLf4E9mk9eYF/wU0AdA3mQ68yZvv+Bhlc75e9kmUFe+JbctKR4YaKGY6K6K/F1tHrKYkASEkfQQ0KJU/ez/wtSf21A6Z2bM/Gg28f/6owfIMPWnYuB9VOLqkdIHFUot40uMi9CBvkdwH69zAQfz4jFvmu588klE0usBclGAFs78KM6YWaXHYjHdWVRIUrAqdZw1IP0uYS3uSBUPsbBG/Aq0V+22dg8U5DSu5XmwLB5jT+3c4ScqH3kY5tomRLe+2Dx4K+mAHpgtf10xL6Ayx2y0GFZCf+LB1Va3Trk3ChcaKRF5KvyayFQNSY4AfA47B90asdv== user@hostname </code></pre><h4>SSH into VPS</h4><p>Next, we login to our VPS and specify -i what key to use. The -i is only needed if you have more than one key. The -v displays verbose or details of what the command is doing in the terminal.</p><pre><code class="language-plaintext">ssh -i ~/.ssh/id_rsa root@123.123.123.123</code></pre><p>Success! Now, we are able to update and upgrade our packages.</p><h3>Prepping Linux Environment</h3><h4>Update Sources & Packages</h4><pre><code class="language-plaintext">apt-get update && apt-get upgrade</code></pre><h4>Disable Ubuntu Sudo Timeout </h4><p>In Ubuntu, sudo has a timeout built in for ease of use. I personally remove this timeout; without knowing you are using sudo will create all kinds of headaches in the future. When you make use of root privileges, we must explicitly type sudo each command.</p><pre><code class="language-plaintext">sudo visudo</code></pre><p>edit and add the following line to the config file</p><pre><code class="language-plaintext">Defaults env_reset, timestamp_timeout=00</code></pre><h3>Setting Up The Firewall</h3><p>After we have logged in via SSH for root user account. I recommend installing a powerful firewall called: <strong>ufw</strong></p><pre><code class="language-plaintext">apt-get install ufw</code></pre><pre><code class="language-plaintext">ufw allow ssh</code></pre><p>Display the status of the firewall and determine if ssh has been allowed. If nomenclature <i>ssh</i> doesn't add the ports, we do this manually with ufw allow 22/udp & ufw all 22/tcp. Port 22 is the common port SSH server makes use of; we are able to change this port for extra hardening, but for the sake of this tutorial, we will use port 22.</p><pre><code class="language-plaintext">ufw status </code></pre><pre><code class="language-plaintext">To Action From |
||||
-- ------ ---- |
||||
22/tcp ALLOW Anywhere |
||||
22/udp ALLOW Anywhere</code></pre><p>Now, we enable the firewall <strong>after</strong> we allow port 22. The SSH connection should remain open. If it closes, SSH back into your VPS.</p><pre><code class="language-plaintext">ufw enable </code></pre><h4>Check If Port Is Open </h4><p>Once telnet is ran, ssh information should populate</p><pre><code class="language-plaintext">telnet 123.123.123.123 22</code></pre><pre><code class="language-plaintext">Trying 123.123.123.123... |
||||
Connected to 123.123.123.123. |
||||
Escape character is '^]'. |
||||
SSH-X.0-OpenSSH_X.2p1 Ubuntu-Xubuntu0.2 |
||||
|
||||
Invalid SSH identification string. |
||||
Connection closed by foreign host.</code></pre><h3>Creating New Users & Permissions</h3><p>To further expand on the garden, we must define a secure space for each plant or service we are running. To manage each service, like dns, mail, gitea, etc... we create a new user for each of these environments. This separation is important for operational security (OPSEC).</p><pre><code class="language-plaintext">adduser username</code></pre><blockquote><p>Note: If we want to use Dockerfile or auto script without prompts, we make use of the <strong>useradd</strong> command.</p></blockquote><pre><code class="language-plaintext">Adding user `username' ... |
||||
Adding new group `username' (1003) ... |
||||
Adding new user `username' (1002) with group `username' ... |
||||
Creating home directory `/home/username' ... |
||||
Copying files from `/etc/skel' ... |
||||
New password: </code></pre><p>Next, if the user should have sudo permission, we do the following.</p><pre><code class="language-plaintext">usermod -a -G sudo username</code></pre><h4>Prove User was Created</h4><pre><code class="language-plaintext">cat /etc/passwd</code></pre><pre><code class="language-plaintext">... |
||||
username:x:1001:1002:User Name,,,:/home/username:/bin/bash |
||||
...</code></pre><h4>Logging In with New Username</h4><pre><code class="language-plaintext">su username</code></pre><h4>Update SSH Config </h4><pre><code class="language-plaintext">sudo nano /etc/ssh/sshd_config</code></pre><p>Add sudo to the <strong>AllowGroups</strong> like so: </p><pre><code class="language-plaintext">AllowGroups wheel root sudo</code></pre><p>Next, we disable root login since we will only have root privileges when using sudo. </p><pre><code class="language-plaintext">PermitRootLogin no</code></pre><h4>SSH Directory Creation </h4><p>For New Username Creating new user access to SSH login. When you connect to new username@ip, the vps user needs the public key for verification of authorized user. Authorized users with correct <strong>private key</strong> will be able to login to vps via ssh protocol. </p><pre><code class="language-plaintext">mkdir ~/.ssh` `nano ~/.ssh/authorized_keys</code></pre><p>Paste your public key we created earlier into the authorized_keys file.</p><h4>Update file & folder permissions</h4><pre><code class="language-plaintext">chmod 700 ~/.ssh` `chmod 600 ~/.ssh/authorized_keys</code></pre><h4>Restart SSH service </h4><pre><code class="language-plaintext">sudo service ssh restart</code></pre><pre><code class="language-plaintext">exit</code></pre><p>In conclusion, we are now able to login via SSH with new user and have also disabled root user logins. This process will have to be done for each user that is created. </p><h3>Backups with Rsync Superpowers!</h3><p>After all our hard work and focus, we should backup our VPS and create scheduled routines. Depending on your use case, I would recommend at least weekly backups. The following command is quite complex, but, essentially we are discarding folders we don't need, backing up the entire VPS to our local machine and preserving all permissions and file integrity from the VPS.</p><ul><li>rsync - A fast, versatile, local and remote file-copying utility </li><li>aAXv - The files are transferred in "archive" mode, which ensures that symbolic links, devices, permissions, ownerships,modification times, ACLs, and extended attributes are preserved.</li><li>/ = Source root directory</li><li>--exclude Excludes the given directories from backup.</li></ul><pre><code class="language-plaintext">sudo rsync -aAXv --rsh="ssh -i /home/user/.ssh/id_rsa" --recursive --progress --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/backups/*"} user@123.123.123.123:/ /home/user/VPS/Backups/</code></pre><h4>Sources</h4><ul><li>Full System Backup Using Rsync - <a href="https://wiki.archlinux.org/title/Rsync#Full_system_backup">https://wiki.archlinux.org/title/Rsync#Full_system_backup</a></li></ul> |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,52 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T20:31:26.944Z |
||||
layout: post |
||||
title: Setup a Secure NGINX HTTPS Web Server with Let's Encrypt + Strapi 4.0 Headless CMS |
||||
subheading: Static Websites with CMS |
||||
slug: setup-a-secure-nginx-https-web-server-with-let-s-encrypt-strapi-4-0-headless-cms |
||||
date: 2022-05-24 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/santa_rudolph_unsplash_0ae8e3d5a7.webp |
||||
banner_image_description: Two feet wearing socks beside each other with faces of Santa Clause and another of Rudolph |
||||
category: How-to |
||||
tags: Nginx, Strapi, SSL, Headless CMS, JAMstack, |
||||
--- |
||||
<h2>General</h2><p>For this tutorial, we will launch a secure SSL NGINX web server for your website domain example.org and enable an API to be consumed from the subdomain i.e. <i>api.example.org</i> with Strapi 4.0. </p><blockquote><p><i><strong>Tip</strong></i>: For each reference, I add the <strong>[reference name]</strong> in brackets at the end of the transmission. [<strong>this is an example</strong>]</p></blockquote><h3>Requirements</h3><ul><li>a Ubuntu Linux 20.04 VPS with SSH access - CLI knowledge </li><li>a registered web domain i.e. example.org </li><li>Basic knowledge of DNS and managing a VPS with SSH </li></ul><h3>Dependencies & Packages </h3><ol><li>NodeJS v12 or v14 (v14 is recommended for Strapi 4.0) </li><li>Npm v6+ & Yarn (Yarn is optional) - Certbot with Let's Encrypt </li><li>Nano editor </li></ol><h2>Prepare Operating System </h2><p>Let's Begin! We begin by installing nginx, certbot and verifying versions Strapi needs. Keep in mind, if you are reading this from the future, the versions will change. </p><h3>Update System </h3><pre><code class="language-plaintext">sudo apt update</code></pre><h3>Install Nginx Certbot Packages </h3><pre><code class="language-plaintext">sudo apt install certbot python3-certbot-nginx</code></pre><h3>Install NGINX & verify version </h3><pre><code class="language-plaintext">sudo apt install nginx``` ```node -v && nginx -v</code></pre><blockquote><p><i><strong>Tip</strong></i>: Strapi recommends nodejs v14, but v12 works. </p></blockquote><h3>Install Yarn (Corepack) </h3><p><code>npm i -g corepack</code> <strong>[Install Yarn]</strong> </p><h2>Configure NGINX </h2><p>Next, we will configure your newly installed Nginx server. By default the configurations are located at: <code>/etc/nginx/ & /etc/nginx/sites-available/</code>. To keep things tidy and organized, we create a new api.example.org conf for each domain we are publicly facing to WWW. </p><h3>Make Directory & Copy Default HTML page </h3><pre><code class="language-plaintext">sudo mkdir -p /var/www/api.example.org/html/</code></pre><pre><code class="language-plaintext">sudo cp -R /var/www/html/index.nginx-debian.html /var/www/api.example.org/html/index.html</code></pre><h3>Duplicate Default Config </h3><pre><code class="language-plaintext">sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/api.example.org</code></pre><h3>Update NGINX api.example.org Config File </h3><p>The <strong>Proxy Config</strong> is important and allows the Strapi 4.0 server to run with nginx. In general, the rest allows SSL and redirects all HTTP traffic to HTTPS, plus denies automated user-agents like wget. </p><pre><code class="language-plaintext">server { |
||||
# Redirect all HTTP requests to HTTPS |
||||
listen 80; |
||||
server_name _; |
||||
return 301 https://$host$request_uri; |
||||
# Deny Automated User-Agents |
||||
if ($http_user_agent ~* (netcrawl|npbot|malicious|LWP::Simple|BBBike|wget)) { |
||||
return 403; |
||||
} |
||||
} |
||||
server { |
||||
# Listen HTTPS |
||||
listen 443 ssl http2; # managed by Certbot |
||||
listen [::]:443 ssl http2; |
||||
server_name api.example.org www.api.example.org; |
||||
# sites document root |
||||
root /var/www/api.example.org/html; |
||||
index index.html index.htm; |
||||
# SSL Config |
||||
ssl_certificate /etc/letsencrypt/live/api.example.org/fullchain.pem; # managed by Certbot |
||||
ssl_certificate_key /etc/letsencrypt/live/api.example.org/privkey.pem; # managed by Certbot |
||||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot |
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot |
||||
# Proxy Config |
||||
location / { |
||||
proxy_pass http://strapi; |
||||
proxy_http_version 1.1; |
||||
proxy_set_header X-Forwarded-Host $host; |
||||
proxy_set_header X-Forwarded-Server $host; |
||||
proxy_set_header X-Real-IP $remote_addr; |
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
||||
proxy_set_header X-Forwarded-Proto $scheme; |
||||
proxy_set_header Host $http_host; |
||||
proxy_set_header Upgrade $http_upgrade; |
||||
proxy_set_header Connection "Upgrade"; |
||||
proxy_pass_request_headers on; |
||||
} |
||||
}</code></pre><pre><code class="language-plaintext">CTRL+X, then Y for Yes to save</code></pre><h3>Symbolic Link to sites-enabled </h3><p>This creates a 'mirror' like reference to the sites-available folder.</p><pre><code class="language-plaintext">sudo ln -s /etc/nginx/sites-available/api.exampleorg /etc/nginx/sites-enabled/</code></pre><h4>Verify Symbolic Link </h4><pre><code class="language-plaintext">ls /etc/nginx/sites-enabled/</code></pre><h2>DNS Configuration </h2><p>We now point our domain to the server we are hosting our Strapi on. i.e. 123.123.1.1 </p><h3>Update DNS Settings </h3><p>Depending on your DNS provider or maybe you have your own Domain Name Server, we point our DNS settings for example.org to 123.123.1.1 as type A. I personally recommend Cloudflare. </p><h2>Create SSL Certs </h2><p>We run the automated tool Certbot and create all the needed files and update our <i>api.example.org</i> configuration file. </p><h3>Run Certbot </h3><pre><code class="language-plaintext">sudo certbot --nginx</code></pre><pre><code class="language-plaintext">Choose api.example.org for the site to create certs. for.</code></pre><pre><code class="language-plaintext">Choose option 1 to disable auto redirect HTTP traffic to HTTPS since we already redirected the traffic manually.</code></pre><blockquote><p><strong>Note:</strong> sudo certbot renew --dry-run will test for automatic renewal for your certs. <strong>[Certbot Insturctions]</strong></p></blockquote><h3>Verify api.example.org Updated with Correct Domain</h3><pre><code class="language-plaintext">sudo nano /etc/nginx/sites-enabled/api.example.org</code></pre><h3>Test Config & Restart Nginx </h3><pre><code class="language-plaintext">sudo nginx -t </code></pre><pre><code class="language-plaintext">sudo systemctl restart nginx</code></pre><h2>Firewall Configuration</h2><p>Allow public to connect via HTTPS, we need to open up ports 80 & 443 (HTTP & HTTPS). </p><h3>Allow UFW Ports for Public Traffic </h3><pre><code class="language-plaintext">sudo ufw allow HTTPS</code></pre><pre><code class="language-plaintext">sudo ufw allow HTTP</code></pre><h3>Verify Status & Reload UFW </h3><pre><code class="language-plaintext">sudo ufw status</code></pre><pre><code class="language-plaintext">sudo ufw reload</code></pre><blockquote><p><strong>Tip</strong> sudo ufw allow 'Nginx Full' opens both port 80 & 443 (For SSL / TLS encryption). </p></blockquote><h2>Getting Started with Strapi</h2><p>Now, we must install Strapi 4.0 on the server and launch the Strapi server. </p><h3>Strapi Default Installation </h3><p>Goto desired place to install Strapi project i.e. ~/development/my-strapi-project, then, </p><pre><code class="language-plaintext">yarn create strapi-app my-project</code></pre><blockquote><p><strong>Note</strong>: The default Strapi installation uses SQLite as the database. You are able to use other databases like PostgreSQL. See <strong>[Strapi Installation]</strong> for more details. </p></blockquote><h3>Launch Strapi Development Server </h3><pre><code class="language-plaintext">yarn develop</code></pre><h3>Launch Strapi from Domain URL </h3><pre><code class="language-plaintext">Goto: api.example.com via web browser of your choice.</code></pre><pre><code class="language-plaintext">Follow the instructions and continue creating a new Strapi administrator.</code></pre><h4>References</h4><p><a href="https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment/optional-software/nginx-proxy.html#nginx-upstream">Nginx Strapi Configuration</a></p><p><a href="https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/installation/cli.html#creating-a-strapi-project">Strapi Installation</a></p><p><a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-server-blocks-virtual-hosts-on-ubuntu-16-04">Nginx Server Blocks</a></p><p><a href="https://yarnpkg.com/getting-started/install">Install Yarn</a></p><p><a href="https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal">Certbot Insturctions</a></p><h4>Donations Are Welcome </h4><p><a href="https://cash.app/$sharpeee">Cash App</a> </p> |
@ -0,0 +1,54 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T22:21:09.298Z |
||||
layout: post |
||||
title: How to Setup a Docker Drone CI with HTTPS |
||||
subheading: Obiwon Can Oh Be! A digital C3-PO working beside you! |
||||
slug: how-to-setup-a-docker-drone-ci-with-https |
||||
date: 2022-06-28 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/r2d2_skywalker_c84e2364fe.webp |
||||
banner_image_description: r2d2 and Luke lego people standing on a laptop |
||||
category: How-to |
||||
tags: VPS, SSL, Drone CI, Docker, |
||||
--- |
||||
<blockquote><p>R2D2, you know better than to trust a strange computer! [beeps]</p></blockquote><p>In general, this Drone server enables continuous integration (CI) and is a stepping stone for continuous delivery (CD), including gh-pages and gh-actions like functionality.</p><p>For this to function correctly, you will need to have a working instance of Gitea running on your own system.</p><p>This tutorial doesn’t guide you on how-to create your own HTTPS server using Let’s Encrypt and Certbot. I have added the certbot resource below [Setting Up HTTPS Certs] I will document this in more detail in the near future. However, this article is similar to how to get https on your server setup. <a href="https://sharpetronics.com/blog/tutorials/2021/12/27/setup-nginx-https-web-server-with-lets-encrypt-plus-strapi-4.0-headless-cms/">How-to get HTTPS on your server</a></p><p>As a stack developer and business owner, I am working on so many things! It is difficult to remember everything, so documentation is critical for me to remember.</p><p><strong>Note 1:</strong> If you see a [name-goes-here], I am linking to the references shared at the end of the article. <strong>Note 2:</strong> Be sure your firewall <code>sudo ufw status</code> allows port 80 and 443. <code>sudo ufw allow http</code> && <code>sudo ufw allow https</code>. <strong>Note 3:</strong> If you want to use Docker Engine without sudo, follow this url: <a href="https://docs.docker.com/engine/install/linux-postinstall/">Linux Docker Post-Install</a></p><h3>Requirements</h3><ul><li>Basic Linux CLI knowledge</li><li>A hardened remote SSH server <a href="https://sharpetronics.com/blog/tutorials/2021/07/26/linux-vps-hardening-init/">see Linux VPS hardening</a></li><li>A running Gitea server: Git with a cup of tea</li><li><a href="https://docs.docker.com/engine/install/">Docker Engine</a></li><li>a basic understanding of how to use Docker Engine</li><li>basic Nginx, Gitea and Certbot/Let’s Encrypt experience</li><li>openssl</li></ul><h3>Let’s Begin!</h3><h4>Preparing the Environment</h4><p>Creating our super-duper-shared secret</p><pre><code class="language-plaintext">openssl rand -hex 16 |
||||
bea26a2221fd8090ea38720fc445eca6 |
||||
</code></pre><p>Creating an OAuth application on Gitea</p><ol><li>Goto your git.example.com and login</li><li>Navigate to your profile settings (not the administrator settings, but personal profile)</li><li>At the top below the main navigation bar, click on <strong>Applications</strong></li><li>Scroll down to the bottom of the page and create a new App name and Redirect URI</li></ol><pre><code class="language-plaintext">Applications Name: drone |
||||
Redirect URI: https://drone.example.com/login |
||||
</code></pre><ol><li>Click <strong>Create Application</strong></li><li>Copy and save your <strong>Client Secret</strong>; you will only be able to see this secret one time.</li><li>In the next section, we will use these credentials to authenticate with Gitea and launch the Drone server.</li></ol><h4>Create & configure the Docker Container</h4><p>Download docker drone image from Dockerhub</p><p><code>docker pull drone/drone:2</code> <code>docker image</code></p><p>Begin configuring and starting drone</p><p><i>The below command creates a container and starts the Docker runner. Remember to replace the environment variables below with your Drone server details.</i></p><pre><code class="language-plaintext">docker run \ |
||||
--volume=/var/lib/drone:/data \ |
||||
--env=DRONE_TLS_AUTOCERT=true \ |
||||
--env=DRONE_HTTP_SSL_REDIRECT=true \ |
||||
--env=DRONE_HTTP_SSL_TEMPORARY_REDIRECT=true \ |
||||
--env=DRONE_HTTP_SSL_HOST=drone.example.com \ |
||||
--env=DRONE_HTTP_STS_SECONDS=315360000 \ |
||||
--env=DRONE_SERVER_CERT=/etc/letsencrypt/live/drone.example.com/fullchain.pem \ |
||||
--env=DRONE_SERVER_KEY=/etc/letsencrypt/live/drone.example.com/privkey.pem \ |
||||
--env=DRONE_GITEA_SERVER=https://git.example.com \ |
||||
--env=DRONE_GITEA_CLIENT_ID=e69c443c-6bc2-4a35-000b-a2f36a885400 \ |
||||
--env=DRONE_GITEA_CLIENT_SECRET=3aY2000000c2Np7zX4e1Z9nlYhelENfX7nmWyxsgVixRg \ |
||||
--env=DRONE_RPC_SECRET=bea26a2221fd80900000038720fc445eca6 \ |
||||
--env=DRONE_SERVER_HOST=drone.example.com \ |
||||
--env=DRONE_SERVER_PROTO=https \ |
||||
--env=DRONE_USER_FILTER=gitea-user-account \ |
||||
--publish=80:80 \ |
||||
--publish=443:443 \ |
||||
--restart=always \ |
||||
--detach=true \ |
||||
--name=st-drone-ssl \ |
||||
drone/drone:2 |
||||
</code></pre><p>Going the extra yards</p><p>After you create the docker container, it will automatically restart to remember your configuration, but if you create a shell script, you are able to <code>./shell-script.sh</code> and run the Docker image.</p><pre><code class="language-plaintext">vi shell-script.sh |
||||
copy/paste docker config via CTRL+SHIFT+V |
||||
double check for typos |
||||
hit ESC |
||||
press SHIFT+Z,Z (saves and quits) |
||||
chmod +x shell-script.sh (makes script executable) |
||||
then, run the script with: ./shell-script.sh |
||||
</code></pre><h4>Verify</h4><pre><code class="language-plaintext">docker logs st-drone-ssl |
||||
|
||||
INFO[0000] starting the server |
||||
INFO[0000] successfully pinged the remote server |
||||
</code></pre><h4>Stop & Start Container</h4><pre><code class="language-plaintext">sudo docker container stop st-drone-ssl |
||||
sudo docker container start st-drone-ssl |
||||
</code></pre><h3>Part II - Configure a Drone Runner Pipeline with Docker Engine</h3><p>This article will be shared at a later date.</p><h3>References</h3><ul><li><a href="https://certbot.eff.org/instructions">Setting up HTTPS certs</a></li><li><a href="https://docs.drone.io/server/reference/">Drone Configuration Options</a></li><li><a href="https://docs.drone.io/server/provider/gitea/">Drone Gitea Setup</a></li><li><a href="https://docs.drone.io/server/provider/gitea/">Drone Server Docker Installation</a></li><li><a href="https://www.infoworld.com/article/3271126/what-is-cicd-continuous-integration-and-continuous-delivery-explained.html">What is CI/CD</a></li><li><a href="https://unsplash.com/@studbee">Unsplash - Studbee</a></li></ul><h3>Support</h3><p>If you have any questions, concerns, want to say hi, please join the following channel: <a href="https://discord.gg/HQcvr2JBQv">SharpeTronics Discord Support Channel</a> Eventually, I plan on having a commenting system on here..</p><h3>Donations</h3><p>Recently, I have had many folk as about <strong>how to send me a donation</strong>. If you want to give back andor support my efforts, I have shared various ways to donate. Thank You!</p><ul><li><a href="https://cash.app/$sharpeee">Cash App</a></li><li><a href="https://account.venmo.com/u/seabeeess">Venmo</a></li><li><a href="https://opencollective.com/sharpetronics">Open Collective</a></li></ul> |
@ -0,0 +1,66 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T22:19:12.170Z |
||||
layout: post |
||||
title: How to Setup a Secure Docker Drone Runner with Drone CI |
||||
subheading: BeeYoop BeeDeepBoom Weeop DEEpaEEya |
||||
slug: how-to-setup-a-secure-docker-drone-runner-with-drone-ci |
||||
date: 2022-06-28 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/c3po_a_friend_in_need_74a237a413.webp |
||||
banner_image_description: a picture of c3po from Star Wars |
||||
category: How-to |
||||
tags: Linux, Drone CI, Docker, |
||||
--- |
||||
<blockquote><p>BeeYoop BeeDeepBoom Weeop DEEpaEEya</p></blockquote><p>In general, this article describes how to setup SSL with a Drone Runner. This is part II of a part I series. If you would like to learn how-to setup the Drone Server, please visit: <a href="https://www.sharpetronics.com/blog/tutorials/2022/06/23/how-to-setup-a-docker-drone-ci-with-https/">Setup Drone CI Server</a>.</p><p>This part II creates a pipeline runner with a Docker machine; what that means is, like GitHub Actions, but with Drone super powers. The configuration file is stored as <code>.drone.yml</code> in the root of your site directory and drone server uses that application yml file to do a series of commands or actions within the virtual docker machine.</p><p>This is empowering because you can automate a fresh build every time. Also, you create a <strong>drone trigger</strong> for when you push to a branch master as an example. Here is the configuration of all the possible things you can do. <a href="https://docs.drone.io/pipeline/docker/overview/">Docker Pipelines Overview</a></p><p><strong>Note 1:</strong> If you see a [name-goes-here], I am linking to the references I shared below. <strong>Note 2:</strong> If you want to use Docker Engine without sudo, follow this url: <a href="https://docs.docker.com/engine/install/linux-postinstall/">Linux Docker Post-Install</a></p><h3>Requirements</h3><ul><li>Basic Linux CLI knowledge</li><li>A hardened remote SSH server <a href="https://sharpetronics.com/blog/tutorials/2021/07/26/linux-vps-hardening-init/">see Linux VPS hardening</a></li><li>A running Gitea server: Git with a cup of tea</li><li><a href="https://docs.docker.com/engine/install/">Docker Engine</a></li><li>a basic understanding of how to use Docker Engine</li><li>basic Nginx, Gitea and Certbot/Let’s Encrypt experience</li><li>openssl</li><li>a running drone ci server <a href="https://www.sharpetronics.com/blog/tutorials/2022/06/23/how-to-setup-a-docker-drone-ci-with-https/">see part I</a></li></ul><h3>Let’s Begin!</h3><h4>Pull docker image from dockerhub</h4><p><code>docker pull drone/drone-runner-docker:1</code></p><h4>Make public access to repo in drone GUI</h4><p>For testing, I made sure the repo was publicly available.</p><p><img src="https://dash.sharpetronics.com/uploads/screenshot_drone_gui_9f74a0f0cb.webp" alt="screenshot-drone-gui.webp"></p><h3>Launch a Secure Docker Drone Runner</h3><p>For the <strong>DRONE_RPC_SECRET</strong> use the same ssl secret we created in Part I. See <a href="https://docs.drone.io/runner/docker/configuration/reference/">Configuration</a> for a complete list of configuration options.</p><p>Please see the reference to understand what this docker config is doing. That is important for you to do yourself.</p><pre><code class="language-plaintext">docker run --detach \ |
||||
--volume=/var/run/docker.sock:/var/run/docker.sock \ |
||||
--env=DRONE_RPC_PROTO=https \ |
||||
--env=DRONE_RPC_HOST=drone.example.com \ |
||||
--env=DRONE_RPC_SECRET=bea26a2221fd8090ea38720fc445eca6 \ |
||||
--env=DRONE_RUNNER_CAPACITY=2 \ |
||||
--env=DRONE_RUNNER_NAME=st-runner \ |
||||
--env=DRONE_UI_USERNAME=youruserhere \ |
||||
--env=DRONE_UI_PASSWORD=yourpasshere \ |
||||
--env=DRONE_DEBUG=true \ |
||||
--env=DRONE_TRACE=true \ |
||||
--publish=3000:3000 \ |
||||
--restart=always \ |
||||
--name=st-drone-runner \ |
||||
drone/drone-runner-docker:1 |
||||
</code></pre><h4>A Pipeline Config Example</h4><p>An example of a custom pipeline I have created. I ain’t going to explain this to you in detail; I expect you to determine your own pipeline and this is only for a reference point. Essentially, what you will be doing is launching your own virtual machine for your specific use case scenario.</p><p>In this example, on drone.example.com, I have created a secret pass that needs to be passed to the virtual machine so I can package the build aka <strong>_site</strong> only, then auto push to www_data branch on my git server. Furthermore, I <strong>rsync</strong> this data through an ssh tunnel to a <strong>Gitea Pages</strong> server that serves the <strong>WWW or edge</strong> data.</p><p><strong>Note: 3:</strong> The example configuration is a <strong>.drone.yml</strong> file stored in the root of your site project.</p><pre><code class="language-plaintext">--- |
||||
kind: pipeline |
||||
type: docker |
||||
name: build |
||||
workspace: |
||||
path: /drone/src |
||||
platform: |
||||
os: linux |
||||
arch: amd64 |
||||
trigger: |
||||
branch: |
||||
- master |
||||
steps: |
||||
- name: build-website |
||||
image: ruby:latest |
||||
environment: |
||||
SSH_USER: |
||||
from_secret: ssh_user |
||||
SSH_HOST: |
||||
from_secret: ssh_host |
||||
NO_HOSTKEY: |
||||
from_secret: no_hostkey |
||||
privileged: false |
||||
volumes: |
||||
- name: jekyll |
||||
path: /srv/jekyll |
||||
commands: |
||||
# general vm information for debugging |
||||
- whoami |
||||
- pwd |
||||
- gem environment |
||||
</code></pre><h4>Verify</h4><pre><code class="language-plaintext">docker logs st-drone-runner |
||||
INFO[0000] starting the server |
||||
INFO[0000] successfully pinged the remote server |
||||
</code></pre><h4>Stop & Start Container</h4><pre><code class="language-plaintext">sudo docker container stop st-drone-ssl |
||||
sudo docker container start st-drone-ssl |
||||
</code></pre><h3>References</h3><ul><li><a href="https://docs.drone.io/runner/docker/configuration/reference/">Drone Runner Configuration</a></li><li><a href="https://docs.drone.io/runner/docker/installation/linux/">Drone Runner Docker Installation</a></li><li><a href="https://docs.drone.io/pipeline/docker/overview/">Docker Pipelines Overview</a></li><li><a href="https://unsplash.com/@nietzsche99">Unsplash - Nice M Nshuti</a></li></ul><h3>Support</h3><p>If you have any questions, concerns, want to say hi, please join the following channel: <a href="https://discord.gg/HQcvr2JBQv">SharpeTronics Discord Support Channel</a> Eventually, I plan on having a commenting system on here..</p><h3>Want to buy me a coffee?</h3><p>Recently, I have had many folk as about <strong>how to send me a donation</strong>. If you want to give back andor support my efforts, I have shared various ways to donate. Thank You!</p><ul><li><a href="https://cash.app/$sharpeee">Cash App</a></li><li><a href="https://account.venmo.com/u/seabeeess">Venmo</a></li><li><a href="https://opencollective.com/sharpetronics">Open Collective</a></li></ul> |
@ -0,0 +1,24 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T20:00:04.549Z |
||||
layout: post |
||||
title: Update your Strapi CMS with your own Favicon |
||||
subheading: How-to replace the favicon |
||||
slug: update-your-strapi-cms-with-your-own-favicon |
||||
date: 2022-07-26 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/code_2b5ed5fa9c.webp |
||||
banner_image_description: computer code matrix |
||||
category: How-to |
||||
tags: Jekyll, Strapi, Headless CMS, |
||||
--- |
||||
<p> In this article, we will be replacing the Strapi favicon with your own favicon. This same process is similar to how we replace the login logo <code>AuthLogo</code> and menu logo with <code>MenuLogo</code>. For more details, please visit Strapi documentations example configuration. [<a href="#References">Strapi Documents</a>]</p><blockquote><p><strong>Tip:</strong> This same process may be used to replace the login logo <code>AuthLogo</code> and menu logo with <code>MenuLogo</code>. For more details, please visit <a href="https://docs.strapi.io/developer-docs/latest/development/admin-customization.html#logos">Strapi Documents</a></p></blockquote><p>1. Create an extensions folder at: <code>src/admin/extensions/</code></p><p>2. Upload your favicon into: <code>src/admin/extensions/</code></p><p>3. Replace the <strong>favicon.ico</strong> at: <code>Strapi app root</code> with custom favicon.ico</p><p>4. Update your <code>src/admin/app.js</code> with the following:</p><pre><code class="language-plaintext">// path: src/admin/app.js |
||||
import favicon from './extensions/favicon.png'; |
||||
export default { |
||||
config: { |
||||
// replace favicon with custom icon |
||||
head: { |
||||
favicon: favicon, |
||||
}, |
||||
} |
||||
}</code></pre><p>5. Rebuild, run & revisit your Strapi app <code>yarn build && yarn develop</code></p><blockquote><p><i><strong>Note</strong></i><strong>:</strong> Be certain that the cached favicon is cleared. It can be cached in your web browser and also with your domain management > tool like Cloudflare's CDN</p></blockquote><h4>References</h4><p><a href="https://docs.strapi.io/developer-docs/latest/development/admin-customization.html#configuration-options">Strapi Documents</a></p> |
@ -0,0 +1,64 @@
|
||||
--- |
||||
updatedAt: 2022-12-07T04:44:26.587Z |
||||
layout: post |
||||
title: Upgrade your Crosshair VI Hero Motherboard Firmware with System76's PopOS! |
||||
subheading: I was doing a bit of yak shaving this morning, and it looks like it might have paid off. |
||||
slug: upgrade-your-crosshair-vi-hero-motherboard-firmware-with-system76-s-pop-os |
||||
date: 2022-10-12 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/galactic_andromeda_workstation_393e5d94d4.webp |
||||
banner_image_description: a fresh computer desk with monitors from the Andromeda Galaxy. |
||||
category: How-to |
||||
tags: Repairs, Debugging, Troubleshooting, |
||||
--- |
||||
<p>My grandpa always said: "<i>if it ain't broke, it needs no fixin!</i>" </p><p>I begun having trouble with random occurrences of my computer crashing on both Linux and Window's operating systems. This article details some of the steps I mazed through and will expedite spacetime support for future dilemmas. </p><p>After tinkering and pondering on the possible reasons, I deduced it down to either the GPU, Motherboard or potentially the PSU voltage irregularities. The GPU & RAM worked like a champ while stress testing them. I was unable to reproduce the random occurrence of this hard crash, and both Ubuntu 22.04 and Windows 10 never provided any error logs I could trace through. After each crash, I would restart and save the logs to maybe find a pattern between all the crashes, but sorting through all this didn't even provide a solution!</p><p><strong>The PopOS! logs:</strong></p><pre><code class="language-plaintext">sudo journalctl --since today --output=short > ~/Documents/System\ Logs/today-1.log |
||||
journalctl -p 3 -xb</code></pre><p><strong>The Windows 10 logs:</strong></p><pre><code class="language-plaintext">Windows key + R |
||||
input: eventvwr and tap the enter key |
||||
navigate through the GUI...</code></pre><p>To deduce it further, the physical symptoms were:</p><ol><li>The computer visuals on screen would freeze for a few seconds and then the monitors would all turn off, but the computer fans and motherboard lights stayed online.</li><li>No error logs to trace on both Windows or Linux Ubuntu</li><li>Random occurrences with intense and normal visuals</li><li>It happened with more than one browser like Firefox and Google Chrome</li></ol><p>Normally, I would do a hard reset after it would crash and mistakenly overlooked the error code that was displayed after the crash; anyhow, the QCODE I received was: <strong>08</strong>. Upon further investigation and mazing around with the software bios utilities, I discovered I had a little button that would do all this in a <strong>Flash</strong>.</p><h2>Requirements & Safety</h2><ol><li>Linux OS; Windows 11 is similar, but the commands are different.</li><li>Basic electronic principles * Always make backups</li><li>Create a bootable drive in case bootloader messes up after update (see here)</li><li>Backup procedures in-case BIOS update fails</li><li>A official manual for your motherboard *WARNING:* You are soley responsible for your own hardware; this article is the process of how I have successfully troubleshooted my own hardware.</li></ol><p>1. Get BIOS & Motherboard Information</p><pre><code class="language-plaintext">sudo dmidecode --type 0</code></pre><pre><code class="language-plaintext"># dmidecode 3.3 |
||||
Getting SMBIOS data from sysfs. |
||||
SMBIOS 3.2.0 present. |
||||
Handle 0x0000, DMI type 0, 26 bytes |
||||
BIOS Information |
||||
Vendor: SharpeTronics Inc. |
||||
Version: 1501 |
||||
Release Date: 07/3/2017 |
||||
Address: 0xF0000 |
||||
Runtime Size: 64 kB |
||||
ROM Size: 16 MB |
||||
Characteristics: |
||||
PCI is supported |
||||
APM is supported |
||||
BIOS is upgradeable |
||||
BIOS shadowing is allowed |
||||
Boot from CD is supported |
||||
Selectable boot is supported |
||||
BIOS ROM is socketed |
||||
EDD is supported |
||||
5.25"/1.2 MB floppy services are supported (int 13h) |
||||
3.5"/720 kB floppy services are supported (int 13h) |
||||
3.5"/2.88 MB floppy services are supported (int 13h) |
||||
Print screen service is supported (int 5h) |
||||
8042 keyboard services are supported (int 9h) |
||||
Serial services are supported (int 14h) |
||||
Printer services are supported (int 17h) |
||||
ACPI is supported |
||||
USB legacy is supported |
||||
BIOS boot specification is supported |
||||
Targeted content distribution is supported |
||||
UEFI is supported |
||||
BIOS Revision: 1.17</code></pre><p>The above output allows us to verify the BIOS</p><pre><code class="language-plaintext">sudo dmidecode --type 2</code></pre><pre><code class="language-plaintext">Handle 0x0002, DMI type 2, 15 bytes |
||||
Base Board Information |
||||
Manufacturer: ASUSTeK COMPUTER INC. |
||||
Product Name: CROSSHAIR VI HERO |
||||
Version: Rev 1.xx |
||||
Serial Number: 0x0x0x0x0x0x0x |
||||
Asset Tag: Default string |
||||
Location In Chassis: Default string |
||||
Chassis Handle: 0x0003 |
||||
Type: Motherboard |
||||
Contained Object Handles: 0</code></pre><p>2. Download the Firmware from Manufacturer's Website</p><p>Navigate to the firmware page and download the most recent firmware update for your CROSSHAIR VI HERO: [link](#sources) </p><p>3. After you download the new firmware, we open & rename the file to <strong>C6H.CAP</strong>, then <i>duplicate</i> or move it to the <i>root</i> of the <i>USB device</i>.</p><p>The instructions are provided by the manufacturer; you may discover this information online or the actual manual shipped with your motherboard. For this use case scenario, the ASUS Crosshair VI Hero motherboard has a BIOS button that sweeps or extracts the file and updates your firmware in about 3-5min with a ~17mb file.</p><p>4. Upgrade your Motherboard Firmware</p><p>If you're also upgrading the: ROG CROSSHAIR VI HERO Motherboard to <i>version 8601</i>, the page of reference is located in <strong>"Chapter 2.2 BIOS update utility : USB BIOS Flashback".</strong> To use USB BIOS Flashback:</p><pre><code class="language-plaintext">1. Download the latest BIOS file from the ASUS website. |
||||
2. Extract and rename the BIOS image file to C6H.CAP. |
||||
3. Copy C6H.CAP to the root directory of your USB storage device. |
||||
4. Turn off the system and connect the USB storage device to the USB BIOS Flashback port. |
||||
5. Press the USB BIOS Flashback button. </code></pre><p>The method above allows an owner to update their motherboard without mazing around in the BIOS software. You simply plug-in the USB device into the <strong>correct port</strong> and <strong>press</strong> the button.</p><p>The <strong>button will blink blue slowly then speed up as time progress's</strong>; I spent about 3-5 minutes flashing the BIOS this way; before, I have had horror stories flashing the BIOS with the BIOS. For example, I was unable to successfully make use of the other two tools the manufacturer provided because the software would bug out. The simplest and most effective method is using a USB BIOS Flashback button that is physically located on your motherboard.</p><h2>Other Misc. Testing</h2><p>Some other things I spent doing before I reached a solution were the following:</p><ul><li>Upgraded all disk drivers</li><li>Lots of research </li><li>Re-seated all motherboard connections</li><li>Cleaned and dusted all dust on the grill and fans.</li><li>Cleaned and Reapplied thermal paste to CPU * Re-seated and clean the GPU</li><li>Reinstalled Windows and Linux OS</li><li>Contacted a support channel with another company</li><li>The bug could be related to AMD's fTPM feature. <a href="#sources"><strong>link</strong></a></li><li>...many more...</li></ul><p>In conclusion, the entire machine has been revitalized, including both software and hardware. The bug has been resolved and I can get back to doing other cool stuff and things. In the future, I will include how to repair your bootloader on Ubuntu and Windows after upgrading your BIOS; in the meantime, if you need this ASAP, System76 has a well written article on the topic at hand at <a href="#sources"><strong>link</strong></a>.</p><h3>Sources</h3><p><a href="https://support.system76.com/articles/bootloader/">Repair Your Linux Bootloaders - System76</a></p><p><a href="https://www.tomshardware.com/news/amd-issues-fix-and-workaround-for-ftpm-stuttering-issues">AMD fTPM Stuttering Issues - Toms Hardware</a></p><p><a href="https://rog.asus.com/us/motherboards/rog-crosshair/rog-crosshair-vi-hero-model/helpdesk_bios/">ASUS Crosshair VI Hero Drivers & Manuals</a></p> |
@ -0,0 +1,18 @@
|
||||
--- |
||||
updatedAt: 2022-12-16T23:30:47.443Z |
||||
layout: post |
||||
title: A Fresh, Secure and Tidy Strapi Project from Source |
||||
subheading: A clean work space is a happy work space. |
||||
slug: a-fresh-secure-and-tidy-strapi-project-from-source |
||||
date: 2022-12-16 |
||||
author: Charles |
||||
author_image: /uploads/c_avatar_30ba895a14.webp |
||||
banner_image: /uploads/tidy_9aa686bedb.webp |
||||
banner_image_description: A clean work space is a happy work space |
||||
category: How-to |
||||
tags: Strapi, Linux, |
||||
--- |
||||
<p>In this tutorial, we will be creating and rebuilding a fresh Strapi application. This article will be beneficial for future upgrades and aid in documentation for other sites being created. </p><h4>Requirements:</h4><ul><li>Yarn or NPM</li><li>Linux CLI knowledge</li><li>A previous or new Strapi project</li></ul><h4>0. Make a complete backup of your current, soon to be previous Strapi project.</h4><p><code>cp -rv strapi-project ./strapi-project_backup</code></p><h4>1. File directory should have the following like</h4><p><i>1a. If you have a previous Strapi project, remove the following files and folders.</i></p><ul><li>build</li><li>.cache</li><li>database</li><li>node_modules</li><li>.strapi-updater.json</li><li>yarn.lock</li></ul><p>then, the following folders should be leftover.</p><ul><li>config dir</li><li>public dir</li><li>src dir</li><li>favicon.ico</li><li>package.json</li><li>.env <i>(if you have a previous Strapi build)</i></li><li>.tmp dir <i>(as of 4.5.4, we must keep this temporary directory)</i></li></ul><h4>2. Install the Strapi Application</h4><p>From the appropriate file structure we begin by installing the appropriate packages from the package.json. <br>This will create a directory called node_modules and a yarn.lock file.</p><p>I also recommend disabling the tracking analytics by updating the package.json to the following:</p><p><strong>./package.json</strong></p><pre><code class="language-plaintext"> "strapi": { |
||||
"uuid": false |
||||
}, |
||||
…</code></pre><p>Finally, we <code>yarn install && yarn build && yarn develop</code></p><h4>References:</h4><p><strong>Axios Wrapper Bug:</strong> <a href="https://github.com/strapi/strapi/pull/15131">https://github.com/strapi/strapi/pull/15131</a> <br><strong>Unsplash by Toa Heftiba</strong> <a href="https://unsplash.com/@heftiba">https://unsplash.com/@heftiba</a></p> |
@ -0,0 +1,625 @@
|
||||
.section { |
||||
text-align: center; |
||||
} |
||||
|
||||
body a { |
||||
color: #5b5b5b; |
||||
} |
||||
|
||||
body.landing { |
||||
background-attachment: scroll !important; |
||||
background-color: #fff; |
||||
} |
||||
|
||||
body.single { |
||||
background-image: none; |
||||
|
||||
} |
||||
|
||||
ul.actions li { |
||||
padding: 0em; |
||||
} |
||||
|
||||
h1, h2, h3, h4, h5, h6, header.major h1, .icon.style3 { |
||||
color: #404040; |
||||
} |
||||
|
||||
.product-font-price { |
||||
font-size: .5em; |
||||
} |
||||
#thank-you-message { |
||||
display: none; |
||||
} |
||||
|
||||
#thank-you-message.show { |
||||
display: block; |
||||
} |
||||
|
||||
#newsletter-form { |
||||
border: none; |
||||
} |
||||
|
||||
#newsletter-form.hide { |
||||
display: none; |
||||
} |
||||
|
||||
strong, b { |
||||
font-weight: 700; |
||||
} |
||||
|
||||
header.major { |
||||
padding: 5.5em 0 .5em 0; |
||||
} |
||||
|
||||
.logo { |
||||
margin-right: 21px; |
||||
} |
||||
|
||||
.features { |
||||
margin-bottom: 0px; |
||||
border: none; |
||||
} |
||||
.features h4 { |
||||
padding-top: 1em; |
||||
} |
||||
|
||||
#banner { |
||||
padding: 6em 2em 5em 2em; |
||||
} |
||||
|
||||
.wave-container > svg { |
||||
display: block; |
||||
margin-bottom: -1px; |
||||
} |
||||
|
||||
#main .inner { |
||||
border-radius: .3em; |
||||
} |
||||
|
||||
.no-padding { |
||||
padding: 0px !important; |
||||
} |
||||
|
||||
.hero { |
||||
display: flex; |
||||
max-height: 35vw; |
||||
overflow: hidden; |
||||
align-items: center; |
||||
margin-bottom: 2.4em; |
||||
border-top-left-radius: .3em; |
||||
border-top-right-radius: .3em; |
||||
} |
||||
|
||||
.hero > .image.fit { |
||||
border-radius: 0px; |
||||
} |
||||
|
||||
.meta { |
||||
-moz-align-items: left; |
||||
-webkit-align-items: left; |
||||
-ms-align-items: left; |
||||
display: -moz-flex; |
||||
display: -webkit-flex; |
||||
display: -ms-flex; |
||||
display: flex; |
||||
-moz-justify-content: left; |
||||
-webkit-justify-content: left; |
||||
-ms-justify-content: left; |
||||
justify-content: left; |
||||
border-left: 0; |
||||
margin: 0 0 1em 0; |
||||
padding-top: 0; |
||||
padding: 0; |
||||
text-align: left; |
||||
width: 100%; |
||||
} |
||||
|
||||
.meta > * { |
||||
border-left: solid 1px rgba(160, 160, 160, 0.3); |
||||
margin-left: 2em; |
||||
padding-left: 2em; |
||||
} |
||||
|
||||
.meta .published { |
||||
color: #3c3b3b; |
||||
display: block; |
||||
font-size: 0.7em; |
||||
font-weight: 800; |
||||
letter-spacing: 0.25em; |
||||
margin-top: 0.5em; |
||||
text-transform: uppercase; |
||||
white-space: nowrap; |
||||
} |
||||
|
||||
.meta > :first-child { |
||||
border-left: 0; |
||||
margin-left: 0; |
||||
padding-left: 0; |
||||
} |
||||
|
||||
.meta .author .name { |
||||
margin: 0 0 0 1.5em; |
||||
} |
||||
|
||||
.author { |
||||
display: -moz-flex; |
||||
display: -webkit-flex; |
||||
display: -ms-flex; |
||||
display: flex; |
||||
-moz-flex-direction: row; |
||||
-webkit-flex-direction: row; |
||||
-ms-flex-direction: row; |
||||
flex-direction: row; |
||||
-moz-align-items: center; |
||||
-webkit-align-items: center; |
||||
-ms-align-items: center; |
||||
align-items: center; |
||||
-moz-justify-content: -moz-flex-end; |
||||
-webkit-justify-content: -webkit-flex-end; |
||||
-ms-justify-content: -ms-flex-end; |
||||
justify-content: flex-end; |
||||
border-bottom: 0; |
||||
font-size: 0.6em; |
||||
font-weight: 400; |
||||
letter-spacing: 0.25em; |
||||
text-transform: uppercase; |
||||
white-space: nowrap; |
||||
} |
||||
|
||||
.author .name { |
||||
-moz-transition: border-bottom-color 0.2s ease; |
||||
-webkit-transition: border-bottom-color 0.2s ease; |
||||
-ms-transition: border-bottom-color 0.2s ease; |
||||
transition: border-bottom-color 0.2s ease; |
||||
border-bottom: dotted 1px rgba(160, 160, 160, 0.65); |
||||
display: block; |
||||
margin: 0 1.5em 0 0; |
||||
} |
||||
|
||||
.author:hover .name { |
||||
border-bottom-color: transparent; |
||||
} |
||||
|
||||
a.author { |
||||
text-decoration: none; |
||||
} |
||||
|
||||
.author img { |
||||
border-radius: 100%; |
||||
display: block; |
||||
width: 4em; |
||||
} |
||||
|
||||
.post { |
||||
padding: 1em 1em 0em 1em; |
||||
margin-bottom: 2em; |
||||
border-radius: .3em; |
||||
box-shadow: 1px 3px 7px -2px #777; |
||||
-webkit-box-shadow: 1px 3px 7px -2px #777; |
||||
-moz-box-shadow: 1px 3px 7px -2px #777; |
||||
display: flex; |
||||
flex-direction: column; |
||||
transition: .25s ease; |
||||
} |
||||
|
||||
.vert-expand { |
||||
display: grid; |
||||
} |
||||
|
||||
.post:hover { |
||||
-webkit-box-shadow: 1px 9px 7px -2px #888; |
||||
-moz-box-shadow: 1px 9px 7px -2px #888; |
||||
box-shadow: 1px 9px 7px -2px #888; |
||||
transition: .25s ease; |
||||
} |
||||
|
||||
.post > footer .stats { |
||||
cursor: default; |
||||
list-style: none; |
||||
padding: 0; |
||||
} |
||||
|
||||
.post > footer .stats > :first-child { |
||||
border-left: 0; |
||||
margin-left: 0; |
||||
padding-left: 0; |
||||
} |
||||
|
||||
.post > footer { |
||||
display: -moz-flex; |
||||
display: -webkit-flex; |
||||
display: -ms-flex; |
||||
display: flex; |
||||
-moz-align-items: center; |
||||
-webkit-align-items: center; |
||||
-ms-align-items: center; |
||||
align-items: center; |
||||
flex-wrap: wrap-reverse; |
||||
} |
||||
|
||||
.post > footer .stats li { |
||||
border-left: solid 1px rgba(160, 160, 160, 0.3); |
||||
display: inline-block; |
||||
font-family: "Raleway", Helvetica, sans-serif; |
||||
font-size: 0.6em; |
||||
font-weight: 400; |
||||
letter-spacing: 0.25em; |
||||
line-height: 1; |
||||
margin: 0 0 0 2em; |
||||
margin-left: 2em; |
||||
padding: 0 0 0 2em; |
||||
padding-left: 2em; |
||||
text-transform: uppercase; |
||||
} |
||||
|
||||
.post > footer ul { |
||||
margin: 0 0 1em 0; |
||||
} |
||||
|
||||
.post > footer ul.actions li { |
||||
padding: 0 0 0 1.2em !important; |
||||
} |
||||
|
||||
.post > footer .actions { |
||||
-moz-flex-grow: 1; |
||||
-webkit-flex-grow: 1; |
||||
-ms-flex-grow: 1; |
||||
flex-grow: 1; |
||||
margin-left: -1.2em; |
||||
} |
||||
|
||||
.button.primary { |
||||
background-color: #3c3c3c; |
||||
color: #5b5b5b; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.button.primary:hover { |
||||
background-color: #e1bc63; |
||||
} |
||||
|
||||
@media only screen and (max-width: 480px) { |
||||
ul.actions:not(.fixed) li { |
||||
padding: .5em 0 .5em 0; |
||||
} |
||||
/* ----- mobile featured product ----- */ |
||||
|
||||
.post.featured.product.no-padding { |
||||
margin: 0 0 1em 0; |
||||
} |
||||
.col-6.col-12-small.product-hero-text.vert-expand { |
||||
padding: 0 0 0 1.3em; |
||||
} |
||||
.button.primary.fit.snipcart-add-item { |
||||
margin-bottom: 1.5em; |
||||
} |
||||
|
||||
/* ----- end mobile featured product ----- */ |
||||
|
||||
ul.actions:not(.fixed) li:first-child { |
||||
padding-top: .5em; |
||||
} |
||||
.ptrail { |
||||
margin-left: 0em !important; |
||||
text-align: center; |
||||
} |
||||
.ptrail li { |
||||
padding: 0 0 0 0em !important; |
||||
} |
||||
.ptrail li:first-child { |
||||
margin: 0px; |
||||
} |
||||
input[type="submit"], input[type="reset"], input[type="button"], button, .button { |
||||
padding: 0 2.9em; |
||||
} |
||||
/* ---------Back to Top------------- */ |
||||
#myBtn { |
||||
padding: 0 .50em; |
||||
display: none; |
||||
position: fixed; |
||||
bottom: .25em !important; |
||||
right: .25em !important; |
||||
} |
||||
} |
||||
|
||||
#footer .copyright a, #footer .copyright { |
||||
text-decoration: none; |
||||
color: #5b5b5b; |
||||
} |
||||
|
||||
#footer .copyright a:hover { |
||||
color: #000; |
||||
} |
||||
|
||||
#footer .menu a { |
||||
color: #5b5b5b; |
||||
} |
||||
|
||||
.major.special.journal { |
||||
padding: 0px; |
||||
} |
||||
|
||||
//Core Media Landing Page Resolution Fix |
||||
@media only screen and (min-width: 2000px) { |
||||
#banner { |
||||
padding: 6em 2em 35em 2em; |
||||
} |
||||
body { |
||||
background-size: auto, contain; |
||||
|
||||
&.landing { |
||||
background-size: auto, contain; |
||||
} |
||||
} |
||||
} |
||||
|
||||
@media only screen and (max-width: 1300px) { |
||||
#banner { |
||||
padding: 6em 2em 22em 2em; |
||||
} |
||||
} |
||||
@media only screen and (max-width: 770px) { |
||||
#banner { |
||||
padding: 6em 2em 25em 2em; |
||||
} |
||||
} |
||||
|
||||
//Paginations |
||||
|
||||
.page_number { |
||||
-moz-justify-content: right; |
||||
-webkit-justify-content: right; |
||||
-ms-justify-content: right; |
||||
justify-content: right; |
||||
display: flex; |
||||
} |
||||
|
||||
.actions.pagination { |
||||
-moz-justify-content: space-between; |
||||
-webkit-justify-content: space-between; |
||||
-ms-justify-content: space-between; |
||||
justify-content: space-between; |
||||
margin-top: 2em; |
||||
margin-bottom: 0em; |
||||
} |
||||
|
||||
.pagination .button.primary { |
||||
background: #f2f2f2; |
||||
color: #5b5b5b !important; |
||||
border: 1px #b7b7b7 solid; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.pagination .button.primary li a { |
||||
color: #5b5b5b; |
||||
} |
||||
|
||||
//Page trail |
||||
.ptrail { |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
.ptrail li { |
||||
height: auto; |
||||
width: 3em; |
||||
border: 1px solid #b7b7b7; |
||||
background-color: #f2f2f2; |
||||
border-radius: .25em; |
||||
margin-left: .25em; |
||||
font-weight: bold; |
||||
text-align: center; |
||||
padding: 0px !important; |
||||
} |
||||
|
||||
.ptrail .selected { |
||||
background-color: #6c6a6a; |
||||
} |
||||
|
||||
.ptrail .selected a { |
||||
color: white; |
||||
} |
||||
|
||||
//Products Listing Page |
||||
|
||||
//Product Categories Navbar |
||||
.product-cat ul { |
||||
list-style:none; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
padding: 1em; |
||||
} |
||||
.product-cat a { |
||||
font-weight: bold; |
||||
} |
||||
//Product Headline Image |
||||
.product-headline-flex { |
||||
object-fit: cover; |
||||
object-position: top; |
||||
margin: 0px; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
div.product-hero-text { |
||||
padding: 0 0 0 .5em; |
||||
} |
||||
.product-hero-text p { |
||||
padding-bottom: .5em; |
||||
} |
||||
@media only screen and (min-width: 1680px) { |
||||
.product-hero-text p { |
||||
padding-bottom: 1.5em; |
||||
} |
||||
} |
||||
.headline-col-limit { //a weird bug when setting max-height on .product-headline-flex, therefore, setting col max-height did the trick. |
||||
max-height: 25.5em; |
||||
} |
||||
|
||||
.product a { |
||||
text-decoration: none; |
||||
} |
||||
|
||||
.product .image.fit { |
||||
height: 12em; |
||||
} |
||||
|
||||
.product img { |
||||
border-radius: .3em .3em 0 0; |
||||
} |
||||
|
||||
.product img.image.fit { |
||||
margin: 0 0 1em 0; |
||||
object-fit: cover; |
||||
} |
||||
|
||||
.product p { |
||||
margin-bottom: 1.5em; |
||||
} |
||||
|
||||
ul.actions { |
||||
margin-left: 0px; |
||||
} |
||||
|
||||
.product p, .product h2, .product h3, .product h4, .product ul.actions { |
||||
padding-left: .5em; |
||||
padding-right: .5em; |
||||
} |
||||
|
||||
.product ul.actions { |
||||
margin-bottom: .5em; |
||||
margin-top: auto; |
||||
} |
||||
|
||||
.featured.product picture { |
||||
object-fit:cover; |
||||
} |
||||
|
||||
.featured.product h3, .featured.product h4 { |
||||
padding-top: .5em; |
||||
} |
||||
|
||||
.featured.product img.image.fit { |
||||
height: 100%; |
||||
object-fit: cover; |
||||
border-top-right-radius: 0em; |
||||
border-bottom-left-radius: .3em; |
||||
} |
||||
|
||||
|
||||
|
||||
//Product Single Page |
||||
|
||||
//Product Shopping Cart |
||||
.product-cart ul { |
||||
list-style:none; |
||||
padding: .2em 0 0 0; |
||||
display: flex; |
||||
justify-content: flex-end; |
||||
margin: 0 0 1em 0; |
||||
} |
||||
.product-cart a { |
||||
text-decoration: none; |
||||
font-weight: bold; |
||||
} |
||||
.product-cart span { |
||||
padding: 0 .5em 0 .5em; |
||||
} |
||||
.product-cart .button.back { |
||||
margin: 0 0 1em 0; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
//Product Details |
||||
.headline h1 { |
||||
margin-bottom: 0em; |
||||
} |
||||
.product-details ul { |
||||
list-style:none; |
||||
padding-left: 0px; |
||||
margin-bottom: .5em; |
||||
} |
||||
.product-details ul li { |
||||
padding-left: 0px; |
||||
} |
||||
|
||||
//Product Image |
||||
.product-flex { |
||||
max-height: 16em; |
||||
min-height: 16em; |
||||
object-fit: cover; |
||||
object-position: top; |
||||
width: 100%; |
||||
height: 16em; |
||||
border-radius: .3em; |
||||
} |
||||
|
||||
//Product Description |
||||
.product-desc h3 { |
||||
margin-bottom: 0em; |
||||
margin-top: .5em; |
||||
} |
||||
|
||||
.product-desc p { |
||||
margin: 0 0 1.0em 0; |
||||
} |
||||
|
||||
//Related Products Section |
||||
.related-items { |
||||
margin-top: 2em; |
||||
} |
||||
|
||||
.related-products h3 { |
||||
margin-bottom: .5em; |
||||
} |
||||
|
||||
.fas.fa-shopping-basket.fa-2x:hover { |
||||
color: #e1bc63; |
||||
} |
||||
/* ---------Comment Discussion Styling------------- */ |
||||
ul.simple-nested li { |
||||
margin-left: 3em; |
||||
} |
||||
|
||||
div.comment { |
||||
background-color: #fff; |
||||
padding: 1em; |
||||
} |
||||
|
||||
em.date { |
||||
font-size: .75em |
||||
} |
||||
|
||||
section.comments ul { |
||||
list-style: disclosure-closed; |
||||
} |
||||
|
||||
.hidden { |
||||
display: none; |
||||
} |
||||
|
||||
/* ---------Back to Top------------- */ |
||||
/* https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_scroll_to_top */ |
||||
#myBtn { |
||||
display: none; |
||||
position: fixed; |
||||
bottom: 1em; |
||||
right: 1em; |
||||
z-index: 99; |
||||
font-size: 18px; |
||||
border: none; |
||||
outline: none; |
||||
background-color: #f5f5f5; |
||||
color: white; |
||||
cursor: pointer; |
||||
border-radius: 4px; |
||||
} |
||||
|
||||
#myBtn:hover { |
||||
background-color: #67c3af3b; |
||||
} |
||||
|
||||
.snipcart-modal__container { |
||||
z-index: 999999999; |
||||
} |
||||
|
@ -0,0 +1,417 @@
|
||||
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ |
||||
|
||||
/** |
||||
* 1. Set default font family to sans-serif. |
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling |
||||
* user zoom. |
||||
*/ |
||||
|
||||
html { |
||||
font-family: sans-serif; /* 1 */ |
||||
-ms-text-size-adjust: 100%; /* 2 */ |
||||
-webkit-text-size-adjust: 100%; /* 2 */ |
||||
} |
||||
|
||||
/** |
||||
* Remove default margin. |
||||
*/ |
||||
|
||||
body { |
||||
margin: 0; |
||||
} |
||||
|
||||
/* HTML5 display definitions |
||||
========================================================================== */ |
||||
|
||||
/** |
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9. |
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11 |
||||
* and Firefox. |
||||
* Correct `block` display not defined for `main` in IE 11. |
||||
*/ |
||||
|
||||
article, |
||||
aside, |
||||
details, |
||||
figcaption, |
||||
figure, |
||||
footer, |
||||
header, |
||||
hgroup, |
||||
main, |
||||
menu, |
||||
nav, |
||||
section, |
||||
summary { |
||||
display: block; |
||||
} |
||||
|
||||
/** |
||||
* 1. Correct `inline-block` display not defined in IE 8/9. |
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. |
||||
*/ |
||||
|
||||
audio, |
||||
canvas, |
||||
progress, |
||||
video { |
||||
display: inline-block; /* 1 */ |
||||
vertical-align: baseline; /* 2 */ |
||||
} |
||||
|
||||
/** |
||||
* Prevent modern browsers from displaying `audio` without controls. |
||||
* Remove excess height in iOS 5 devices. |
||||
*/ |
||||
|
||||
audio:not([controls]) { |
||||
display: none; |
||||
height: 0; |
||||
} |
||||
|
||||
/** |
||||
* Address `[hidden]` styling not present in IE 8/9/10. |
||||
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. |
||||
*/ |
||||
|
||||
[hidden], |
||||
template { |
||||
display: none; |
||||
} |
||||
|
||||
/* Links |
||||
========================================================================== */ |
||||
|
||||
/** |
||||
* Remove the gray background color from active links in IE 10. |
||||
*/ |
||||
|
||||
a { |
||||
background-color: transparent; |
||||
} |
||||
|
||||
/** |
||||
* Improve readability when focused and also mouse hovered in all browsers. |
||||
*/ |
||||
|
||||
a:active, |
||||
a:hover { |
||||
outline: 0; |
||||
} |
||||
|
||||
/* Text-level semantics |
||||
========================================================================== */ |
||||
|
||||
/** |
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome. |
||||
*/ |
||||
|
||||
abbr[title] { |
||||
border-bottom: 1px dotted; |
||||
} |
||||
|
||||
/** |
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome. |
||||
*/ |
||||
|
||||
b, |
||||
strong { |
||||
font-weight: bold; |
||||
} |
||||
|
||||
/** |
||||
* Address styling not present in Safari and Chrome. |
||||
*/ |
||||
|
||||
dfn { |
||||
font-style: italic; |
||||
} |
||||
|
||||
/** |
||||
* Address styling not present in IE 8/9. |
||||
*/ |
||||
|
||||
mark { |
||||
background: #ff0; |
||||
color: #000; |
||||
} |
||||
|
||||
/** |
||||
* Address inconsistent and variable font size in all browsers. |
||||
*/ |
||||
|
||||
small { |
||||
font-size: 80%; |
||||
} |
||||
|
||||
/** |
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers. |
||||
*/ |
||||
|
||||
sub, |
||||
sup { |
||||
font-size: 75%; |
||||
line-height: 0; |
||||
position: relative; |
||||
vertical-align: baseline; |
||||
} |
||||
|
||||
sup { |
||||
top: -0.5em; |
||||
} |
||||
|
||||
sub { |
||||
bottom: -0.25em; |
||||
} |
||||
|
||||
/* Embedded content |
||||
========================================================================== */ |
||||
|
||||
/** |
||||
* Remove border when inside `a` element in IE 8/9/10. |
||||
*/ |
||||
|
||||
img { |
||||
border: 0; |
||||
} |
||||
|
||||
/** |
||||
* Correct overflow not hidden in IE 9/10/11. |
||||
*/ |
||||
|
||||
svg:not(:root) { |
||||
overflow: hidden; |
||||
} |
||||
|
||||
/* Grouping content |
||||
========================================================================== */ |
||||
|
||||
/** |
||||
* Address margin not present in IE 8/9 and Safari. |
||||
*/ |
||||
|
||||
figure { |
||||
margin: 1em 40px; |
||||
} |
||||
|
||||
/** |
||||
* Address differences between Firefox and other browsers. |
||||
*/ |
||||
|
||||
hr { |
||||
-moz-box-sizing: content-box; |
||||
box-sizing: content-box; |
||||
height: 0; |
||||
} |
||||
|
||||
/** |
||||
* Contain overflow in all browsers. |
||||
*/ |
||||
|
||||
pre { |
||||
overflow: auto; |
||||
} |
||||
|
||||
/** |
||||
* Address odd `em`-unit font size rendering in all browsers. |
||||
*/ |
||||
|
||||
code, |
||||
kbd, |
||||
pre, |
||||
samp { |
||||
font-family: monospace, monospace; |
||||
font-size: 1em; |
||||
} |
||||
|
||||
/* Forms |
||||
========================================================================== */ |
||||
|
||||
/** |
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited |
||||
* styling of `select`, unless a `border` property is set. |
||||
*/ |
||||
|
||||
/** |
||||
* 1. Correct color not being inherited. |
||||
* Known issue: affects color of disabled elements. |
||||
* 2. Correct font properties not being inherited. |
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome. |
||||
*/ |
||||
|
||||
button, |
||||
input, |
||||
optgroup, |
||||
select, |
||||
textarea { |
||||
color: inherit; /* 1 */ |
||||
font: inherit; /* 2 */ |
||||
margin: 0; /* 3 */ |
||||
} |
||||
|
||||
/** |
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11. |
||||
*/ |
||||
|
||||
button { |
||||
overflow: visible; |
||||
} |
||||
|
||||
/** |
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`. |
||||
* All other form control elements do not inherit `text-transform` values. |
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. |
||||
* Correct `select` style inheritance in Firefox. |
||||
*/ |
||||
|
||||
button, |
||||
select { |
||||
text-transform: none; |
||||
} |
||||
|
||||
/** |
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` |
||||
* and `video` controls. |
||||
* 2. Correct inability to style clickable `input` types in iOS. |
||||
* 3. Improve usability and consistency of cursor style between image-type |
||||
* `input` and others. |
||||
*/ |
||||
|
||||
button, |
||||
html input[type="button"], /* 1 */ |
||||
input[type="reset"], |
||||
input[type="submit"] { |
||||
-webkit-appearance: button; /* 2 */ |
||||
cursor: pointer; /* 3 */ |
||||
} |
||||
|
||||
/** |
||||
* Re-set default cursor for disabled elements. |
||||
*/ |
||||
|
||||
button[disabled], |
||||
html input[disabled] { |
||||
cursor: default; |
||||
} |
||||
|
||||
/** |
||||
* Remove inner padding and border in Firefox 4+. |
||||
*/ |
||||
|
||||
button::-moz-focus-inner, |
||||
input::-moz-focus-inner { |
||||
border: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
/** |
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in |
||||
* the UA stylesheet. |
||||
*/ |
||||
|
||||
input { |
||||
line-height: normal; |
||||
} |
||||
|
||||
/** |
||||
* It's recommended that you don't attempt to style these elements. |
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width. |
||||
* |
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10. |
||||
* 2. Remove excess padding in IE 8/9/10. |
||||
*/ |
||||
|
||||
input[type="checkbox"], |
||||
input[type="radio"] { |
||||
box-sizing: border-box; /* 1 */ |
||||
padding: 0; /* 2 */ |
||||
} |
||||
|
||||
/** |
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain |
||||
* `font-size` values of the `input`, it causes the cursor style of the |
||||
* decrement button to change from `default` to `text`. |
||||
*/ |
||||
|
||||
input[type="number"]::-webkit-inner-spin-button, |
||||
input[type="number"]::-webkit-outer-spin-button { |
||||
height: auto; |
||||
} |
||||
|
||||
/** |
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome. |
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome |
||||
* (include `-moz` to future-proof). |
||||
*/ |
||||
|
||||
input[type="search"] { |
||||
-webkit-appearance: textfield; /* 1 */ |
||||
-moz-box-sizing: content-box; |
||||
-webkit-box-sizing: content-box; /* 2 */ |
||||
box-sizing: content-box; |
||||
} |
||||
|
||||
/** |
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X. |
||||
* Safari (but not Chrome) clips the cancel button when the search input has |
||||
* padding (and `textfield` appearance). |
||||
*/ |
||||
|
||||
input[type="search"]::-webkit-search-cancel-button, |
||||
input[type="search"]::-webkit-search-decoration { |
||||
-webkit-appearance: none; |
||||
} |
||||
|
||||
/** |
||||
* Define consistent border, margin, and padding. |
||||
*/ |
||||
|
||||
fieldset { |
||||
border: 1px solid #c0c0c0; |
||||
margin: 0 2px; |
||||
padding: 0.35em 0.625em 0.75em; |
||||
} |
||||
|
||||
/** |
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11. |
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets. |
||||
*/ |
||||
|
||||
legend { |
||||
border: 0; /* 1 */ |
||||
padding: 0; /* 2 */ |
||||
} |
||||
|
||||
/** |
||||
* Remove default vertical scrollbar in IE 8/9/10/11. |
||||
*/ |
||||
|
||||
textarea { |
||||
overflow: auto; |
||||
} |
||||
|
||||
/** |
||||
* Don't inherit the `font-weight` (applied by a rule above). |
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X. |
||||
*/ |
||||
|
||||
optgroup { |
||||
font-weight: bold; |
||||
} |
||||
|
||||
/* Tables |
||||
========================================================================== */ |
||||
|
||||
/** |
||||
* Remove most spacing between table cells. |
||||
*/ |
||||
|
||||
table { |
||||
border-collapse: collapse; |
||||
border-spacing: 0; |
||||
} |
||||
|
||||
td, |
||||
th { |
||||
padding: 0; |
||||
} |
@ -0,0 +1,418 @@
|
||||
/* |
||||
* Skeleton V2.0.4 |
||||
* Copyright 2014, Dave Gamache |
||||
* www.getskeleton.com |
||||
* Free to use under the MIT license. |
||||
* http://www.opensource.org/licenses/mit-license.php |
||||
* 12/29/2014 |
||||
*/ |
||||
|
||||
|
||||
/* Table of contents |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– |
||||
- Grid |
||||
- Base Styles |
||||
- Typography |
||||
- Links |
||||
- Buttons |
||||
- Forms |
||||
- Lists |
||||
- Code |
||||
- Tables |
||||
- Spacing |
||||
- Utilities |
||||
- Clearing |
||||
- Media Queries |
||||
*/ |
||||
|
||||
|
||||
/* Grid |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
.container { |
||||
position: relative; |
||||
width: 100%; |
||||
max-width: 960px; |
||||
margin: 0 auto; |
||||
padding: 0 20px; |
||||
box-sizing: border-box; } |
||||
.column, |
||||
.columns { |
||||
width: 100%; |
||||
float: left; |
||||
box-sizing: border-box; } |
||||
|
||||
/* For devices larger than 400px */ |
||||
@media (min-width: 400px) { |
||||
.container { |
||||
width: 85%; |
||||
padding: 0; } |
||||
} |
||||
|
||||
/* For devices larger than 550px */ |
||||
@media (min-width: 550px) { |
||||
.container { |
||||
width: 80%; } |
||||
.column, |
||||
.columns { |
||||
margin-left: 4%; } |
||||
.column:first-child, |
||||
.columns:first-child { |
||||
margin-left: 0; } |
||||
|
||||
.one.column, |
||||
.one.columns { width: 4.66666666667%; } |
||||
.two.columns { width: 13.3333333333%; } |
||||
.three.columns { width: 22%; } |
||||
.four.columns { width: 30.6666666667%; } |
||||
.five.columns { width: 39.3333333333%; } |
||||
.six.columns { width: 48%; } |
||||
.seven.columns { width: 56.6666666667%; } |
||||
.eight.columns { width: 65.3333333333%; } |
||||
.nine.columns { width: 74.0%; } |
||||
.ten.columns { width: 82.6666666667%; } |
||||
.eleven.columns { width: 91.3333333333%; } |
||||
.twelve.columns { width: 100%; margin-left: 0; } |
||||
|
||||
.one-third.column { width: 30.6666666667%; } |
||||
.two-thirds.column { width: 65.3333333333%; } |
||||
|
||||
.one-half.column { width: 48%; } |
||||
|
||||
/* Offsets */ |
||||
.offset-by-one.column, |
||||
.offset-by-one.columns { margin-left: 8.66666666667%; } |
||||
.offset-by-two.column, |
||||
.offset-by-two.columns { margin-left: 17.3333333333%; } |
||||
.offset-by-three.column, |
||||
.offset-by-three.columns { margin-left: 26%; } |
||||
.offset-by-four.column, |
||||
.offset-by-four.columns { margin-left: 34.6666666667%; } |
||||
.offset-by-five.column, |
||||
.offset-by-five.columns { margin-left: 43.3333333333%; } |
||||
.offset-by-six.column, |
||||
.offset-by-six.columns { margin-left: 52%; } |
||||
.offset-by-seven.column, |
||||
.offset-by-seven.columns { margin-left: 60.6666666667%; } |
||||
.offset-by-eight.column, |
||||
.offset-by-eight.columns { margin-left: 69.3333333333%; } |
||||
.offset-by-nine.column, |
||||
.offset-by-nine.columns { margin-left: 78.0%; } |
||||
.offset-by-ten.column, |
||||
.offset-by-ten.columns { margin-left: 86.6666666667%; } |
||||
.offset-by-eleven.column, |
||||
.offset-by-eleven.columns { margin-left: 95.3333333333%; } |
||||
|
||||
.offset-by-one-third.column, |
||||
.offset-by-one-third.columns { margin-left: 34.6666666667%; } |
||||
.offset-by-two-thirds.column, |
||||
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; } |
||||
|
||||
.offset-by-one-half.column, |
||||
.offset-by-one-half.columns { margin-left: 52%; } |
||||
|
||||
} |
||||
|
||||
|
||||
/* Base Styles |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
/* NOTE |
||||
html is set to 62.5% so that all the REM measurements throughout Skeleton |
||||
are based on 10px sizing. So basically 1.5rem = 15px :) */ |
||||
html { |
||||
font-size: 62.5%; } |
||||
body { |
||||
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ |
||||
line-height: 1.6; |
||||
font-weight: 400; |
||||
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; |
||||
color: #222; } |
||||
|
||||
|
||||
/* Typography |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
h1, h2, h3, h4, h5, h6 { |
||||
margin-top: 0; |
||||
margin-bottom: 2rem; |
||||
font-weight: 300; } |
||||
h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} |
||||
h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } |
||||
h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } |
||||
h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } |
||||
h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } |
||||
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } |
||||
|
||||
/* Larger than phablet */ |
||||
@media (min-width: 550px) { |
||||
h1 { font-size: 5.0rem; } |
||||
h2 { font-size: 4.2rem; } |
||||
h3 { font-size: 3.6rem; } |
||||
h4 { font-size: 3.0rem; } |
||||
h5 { font-size: 2.4rem; } |
||||
h6 { font-size: 1.5rem; } |
||||
} |
||||
|
||||
p { |
||||
margin-top: 0; } |
||||
|
||||
|
||||
/* Links |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
a { |
||||
color: #1EAEDB; } |
||||
a:hover { |
||||
color: #0FA0CE; } |
||||
|
||||
|
||||
/* Buttons |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
.button, |
||||
button, |
||||
input[type="submit"], |
||||
input[type="reset"], |
||||
input[type="button"] { |
||||
display: inline-block; |
||||
height: 38px; |
||||
padding: 0 30px; |
||||
color: #555; |
||||
text-align: center; |
||||
font-size: 11px; |
||||
font-weight: 600; |
||||
line-height: 38px; |
||||
letter-spacing: .1rem; |
||||
text-transform: uppercase; |
||||
text-decoration: none; |
||||
white-space: nowrap; |
||||
background-color: transparent; |
||||
border-radius: 4px; |
||||
border: 1px solid #bbb; |
||||
cursor: pointer; |
||||
box-sizing: border-box; } |
||||
.button:hover, |
||||
button:hover, |
||||
input[type="submit"]:hover, |
||||
input[type="reset"]:hover, |
||||
input[type="button"]:hover, |
||||
.button:focus, |
||||
button:focus, |
||||
input[type="submit"]:focus, |
||||
input[type="reset"]:focus, |
||||
input[type="button"]:focus { |
||||
color: #333; |
||||
border-color: #888; |
||||
outline: 0; } |
||||
.button.button-primary, |
||||
button.button-primary, |
||||
input[type="submit"].button-primary, |
||||
input[type="reset"].button-primary, |
||||
input[type="button"].button-primary { |
||||
color: #FFF; |
||||
background-color: #33C3F0; |
||||
border-color: #33C3F0; } |
||||
.button.button-primary:hover, |
||||
button.button-primary:hover, |
||||
input[type="submit"].button-primary:hover, |
||||
input[type="reset"].button-primary:hover, |
||||
input[type="button"].button-primary:hover, |
||||
.button.button-primary:focus, |
||||
button.button-primary:focus, |
||||
input[type="submit"].button-primary:focus, |
||||
input[type="reset"].button-primary:focus, |
||||
input[type="button"].button-primary:focus { |
||||
color: #FFF; |
||||
background-color: #1EAEDB; |
||||
border-color: #1EAEDB; } |
||||
|
||||
|
||||
/* Forms |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
input[type="email"], |
||||
input[type="number"], |
||||
input[type="search"], |
||||
input[type="text"], |
||||
input[type="tel"], |
||||
input[type="url"], |
||||
input[type="password"], |
||||
textarea, |
||||
select { |
||||
height: 38px; |
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ |
||||
background-color: #fff; |
||||
border: 1px solid #D1D1D1; |
||||
border-radius: 4px; |
||||
box-shadow: none; |
||||
box-sizing: border-box; } |
||||
/* Removes awkward default styles on some inputs for iOS */ |
||||
input[type="email"], |
||||
input[type="number"], |
||||
input[type="search"], |
||||
input[type="text"], |
||||
input[type="tel"], |
||||
input[type="url"], |
||||
input[type="password"], |
||||
textarea { |
||||
-webkit-appearance: none; |
||||
-moz-appearance: none; |
||||
appearance: none; } |
||||
textarea { |
||||
min-height: 65px; |
||||
padding-top: 6px; |
||||
padding-bottom: 6px; } |
||||
input[type="email"]:focus, |
||||
input[type="number"]:focus, |
||||
input[type="search"]:focus, |
||||
input[type="text"]:focus, |
||||
input[type="tel"]:focus, |
||||
input[type="url"]:focus, |
||||
input[type="password"]:focus, |
||||
textarea:focus, |
||||
select:focus { |
||||
border: 1px solid #33C3F0; |
||||
outline: 0; } |
||||
label, |
||||
legend { |
||||
display: block; |
||||
margin-bottom: .5rem; |
||||
font-weight: 600; } |
||||
fieldset { |
||||
padding: 0; |
||||
border-width: 0; } |
||||
input[type="checkbox"], |
||||
input[type="radio"] { |
||||
display: inline; } |
||||
label > .label-body { |
||||
display: inline-block; |
||||
margin-left: .5rem; |
||||
font-weight: normal; } |
||||
|
||||
|
||||
/* Lists |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
ul { |
||||
list-style: circle inside; } |
||||
ol { |
||||
list-style: decimal inside; } |
||||
ol, ul { |
||||
padding-left: 0; |
||||
margin-top: 0; } |
||||
ul ul, |
||||
ul ol, |
||||
ol ol, |
||||
ol ul { |
||||
margin: 1.5rem 0 1.5rem 3rem; |
||||
font-size: 90%; } |
||||
li { |
||||
margin-bottom: 1rem; } |
||||
|
||||
|
||||
/* Code |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
code { |
||||
padding: .2rem .5rem; |
||||
margin: 0 .2rem; |
||||
font-size: 90%; |
||||
white-space: nowrap; |
||||
background: #F1F1F1; |
||||
border: 1px solid #E1E1E1; |
||||
border-radius: 4px; } |
||||
pre > code { |
||||
display: block; |
||||
padding: 1rem 1.5rem; |
||||
white-space: pre; } |
||||
|
||||
|
||||
/* Tables |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
th, |
||||
td { |
||||
padding: 12px 15px; |
||||
text-align: left; |
||||
border-bottom: 1px solid #E1E1E1; } |
||||
th:first-child, |
||||
td:first-child { |
||||
padding-left: 0; } |
||||
th:last-child, |
||||
td:last-child { |
||||
padding-right: 0; } |
||||
|
||||
|
||||
/* Spacing |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
button, |
||||
.button { |
||||
margin-bottom: 1rem; } |
||||
input, |
||||
textarea, |
||||
select, |
||||
fieldset { |
||||
margin-bottom: 1.5rem; } |
||||
pre, |
||||
blockquote, |
||||
dl, |
||||
figure, |
||||
table, |
||||
p, |
||||
ul, |
||||
ol, |
||||
form { |
||||
margin-bottom: 2.5rem; } |
||||
|
||||
|
||||
/* Utilities |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
.u-full-width { |
||||
width: 100%; |
||||
box-sizing: border-box; } |
||||
.u-max-full-width { |
||||
max-width: 100%; |
||||
box-sizing: border-box; } |
||||
.u-pull-right { |
||||
float: right; } |
||||
.u-pull-left { |
||||
float: left; } |
||||
|
||||
|
||||
/* Misc |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
hr { |
||||
margin-top: 3rem; |
||||
margin-bottom: 3.5rem; |
||||
border-width: 0; |
||||
border-top: 1px solid #E1E1E1; } |
||||
|
||||
|
||||
/* Clearing |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
|
||||
/* Self Clearing Goodness */ |
||||
.container:after, |
||||
.row:after, |
||||
.u-cf { |
||||
content: ""; |
||||
display: table; |
||||
clear: both; } |
||||
|
||||
|
||||
/* Media Queries |
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */ |
||||
/* |
||||
Note: The best way to structure the use of media queries is to create the queries |
||||
near the relevant code. For example, if you wanted to change the styles for buttons |
||||
on small devices, paste the mobile query code up in the buttons section and style it |
||||
there. |
||||
*/ |
||||
|
||||
|
||||
/* Larger than mobile */ |
||||
@media (min-width: 400px) {} |
||||
|
||||
/* Larger than phablet (also point when grid becomes active) */ |
||||
@media (min-width: 550px) {} |
||||
|
||||
/* Larger than tablet */ |
||||
@media (min-width: 750px) {} |
||||
|
||||
/* Larger than desktop */ |
||||
@media (min-width: 1000px) {} |
||||
|
||||
/* Larger than Desktop HD */ |
||||
@media (min-width: 1200px) {} |
Loading…
Reference in new issue