diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 00000000..453e88fc --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,47 @@ +name: Deploy to GitHub Pages + +on: + release: + types: [published] + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for git info + - uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Install Dependencies + run: npm ci + - name: Build Quartz + run: npx quartz build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: public + + deploy: + needs: build + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 25d07db1..5f96d536 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ tsconfig.tsbuildinfo private/ .replit replit.nix +.sst + diff --git a/README.md b/README.md index 27d6dbdb..6cea8c56 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,123 @@ -# Quartz v4 +# ❍ -> “[One] who works with the door open gets all kinds of interruptions, but [they] also occasionally gets clues as to what the world is and what might be important.” — Richard Hamming -Quartz is a set of tools that helps you publish your [digital garden](https://jzhao.xyz/posts/networked-thought) and notes as a website for free. -Quartz v4 features a from-the-ground rewrite focusing on end-user extensibility and ease-of-use. +- **10x faster** deploys +- Native **multi-region** support +- No more cyclical dependencies +- No stacks or stack resource limits +- No CDK or npm package conflicts +- Native support for **non-AWS** providers -🔗 Read the documentation and get started: https://quartz.jzhao.xyz/ +[Read the full announcement here](https://sst.dev/blog/moving-away-from-cdk.html). -[Join the Discord Community](https://discord.gg/cRFFHYye7t) +_Note: Ion is currently in alpha and only supports deploying Next.js sites and L1 AWS resources. We'll be sharing docs and technical details soon._ -## Sponsors +## Installation -

- - - -

+### curl +sst can be installed using a simple curl command +``` +curl -fsSL https://ion.sst.dev/install | bash +``` + +#### macOS + +`sst` is available via a Homebrew Tap, and as downloadable binary from the [releases](https://github.com/sst/ion/releases/latest) page: + +``` +brew install sst/tap/sst +``` + +To upgrade to the latest version: + +``` +brew upgrade sst +``` + +You might have to run `brew update` before upgrading. + +#### Linux + +`sst` is available as downloadable binaries from the [releases](https://github.com/sst/ion/releases/latest) page. Download the .deb or .rpm from the [releases](https://github.com/sst/ion/releases/latest) page and install with `sudo dpkg -i` and `sudo rpm -i` respectively. + +For arch linux it's available in the [aur](https://aur.archlinux.org/packages/sst-bin) + +#### Windows + +`sst` is available via [scoop](https://scoop.sh/), and as a downloadable binary from the [releases](https://github.com/sst/ion/releases/latest) page: + +``` +scoop bucket add sst https://github.com/sst/scoop-bucket.git +scoop install sst +``` + +To upgrade to the latest version: + +``` +scoop update sst +``` + +#### Manually + +Download the pre-compiled binaries from the [releases](https://github.com/sst/ion/releases/latest) page and copy to the desired location. + +## Quick start + +1. Create a new Next.js app. + + ```bash + npx create-next-app@latest + ``` + +2. Initialize SST in the root of your Next.js app. + + ```bash + cd my-app + sst create + ``` + + - This creates an `sst.config.ts` in your project root. + - `sst.config.ts` is automatically added to the the `exclude` array in `tsconfig.json` to prevent TypeScript from trying to type-check it when building your app + - You should also add `/.sst` and `/.open-next` to your `.gitignore` file. + +3. Deploy! Ensure you have AWS credentials setup and run: + + ```bash + sst deploy + ``` + +### Custom domains + +You can configure the app with a custom domain hosted on [Route 53](https://aws.amazon.com/route53/). + +```js {3} +new Nextjs("Web", { + domain: "my-app.com", +}); +``` + +You can setup `www.my-app.com` redirect to `my-app.com`. + +```js {3} +new Nextjs("Web", { + domain: { + domainName: "my-app.com", + redirects: ["www.my-app.com"], + }, +}); +``` + +Or you can have `www.my-app.com` serve out the same site without redirecting. + +```js {3} +new Nextjs("Web", { + domain: { + domainName: "my-app.com", + aliases: ["www.my-app.com"], + }, +}); +``` + +--- + +Join the `#ion` channel in our [Discord](https://sst.dev/discord) to learn more and contribute. diff --git a/content/.gitkeep b/content/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/content/advanced/index.md b/content/advanced/index.md new file mode 100644 index 00000000..598317ec --- /dev/null +++ b/content/advanced/index.md @@ -0,0 +1,3 @@ +--- +title: Advanced Topics +--- \ No newline at end of file diff --git a/content/advanced/web-security.md b/content/advanced/web-security.md new file mode 100644 index 00000000..540a96ec --- /dev/null +++ b/content/advanced/web-security.md @@ -0,0 +1,3 @@ +--- +title: Web Security +--- \ No newline at end of file diff --git a/content/backend/index.md b/content/backend/index.md new file mode 100644 index 00000000..df27d605 --- /dev/null +++ b/content/backend/index.md @@ -0,0 +1,3 @@ +--- +title: Into the Backend +--- diff --git a/content/backend/nodejs.md b/content/backend/nodejs.md new file mode 100644 index 00000000..6a45372a --- /dev/null +++ b/content/backend/nodejs.md @@ -0,0 +1,3 @@ +--- +title: NodeJS +--- \ No newline at end of file diff --git a/content/backend/requests.md b/content/backend/requests.md new file mode 100644 index 00000000..9bd73cb1 --- /dev/null +++ b/content/backend/requests.md @@ -0,0 +1,3 @@ +--- +title: Requests & Responses +--- \ No newline at end of file diff --git a/content/backend/servers.md b/content/backend/servers.md new file mode 100644 index 00000000..bb9e414b --- /dev/null +++ b/content/backend/servers.md @@ -0,0 +1,5 @@ +--- +title: Servers +--- + +Ever wondered why we call the internet, the "web"? Because it's, in the simplest possible definition, just many computers connected to eachother, just like a spider web. diff --git a/content/best-practices/index.md b/content/best-practices/index.md new file mode 100644 index 00000000..75dcdaca --- /dev/null +++ b/content/best-practices/index.md @@ -0,0 +1,3 @@ +--- +title: Best Practices +--- \ No newline at end of file diff --git a/content/frontend/index.md b/content/frontend/index.md new file mode 100644 index 00000000..008caaf1 --- /dev/null +++ b/content/frontend/index.md @@ -0,0 +1,3 @@ +--- +title: Into the Frontend +--- diff --git a/content/fundamentals/development-environment.md b/content/fundamentals/development-environment.md new file mode 100644 index 00000000..c623508f --- /dev/null +++ b/content/fundamentals/development-environment.md @@ -0,0 +1,3 @@ +--- +title: The Development Environment +--- \ No newline at end of file diff --git a/content/fundamentals/index.md b/content/fundamentals/index.md new file mode 100644 index 00000000..ce6b42a7 --- /dev/null +++ b/content/fundamentals/index.md @@ -0,0 +1,3 @@ +--- +title: Fundamentals +--- diff --git a/content/fundamentals/javascript.md b/content/fundamentals/javascript.md new file mode 100644 index 00000000..b5ff678c --- /dev/null +++ b/content/fundamentals/javascript.md @@ -0,0 +1,3 @@ +--- +title: JavaScript +--- \ No newline at end of file diff --git a/content/fundamentals/package-management.md b/content/fundamentals/package-management.md new file mode 100644 index 00000000..ff6f551f --- /dev/null +++ b/content/fundamentals/package-management.md @@ -0,0 +1,3 @@ +--- +title: Package Management +--- \ No newline at end of file diff --git a/content/fundamentals/the-url.md b/content/fundamentals/the-url.md new file mode 100644 index 00000000..05ce9ff3 --- /dev/null +++ b/content/fundamentals/the-url.md @@ -0,0 +1,3 @@ +--- +title: Understanding the URL +--- \ No newline at end of file diff --git a/content/fundamentals/the-web.md b/content/fundamentals/the-web.md new file mode 100644 index 00000000..cba049b3 --- /dev/null +++ b/content/fundamentals/the-web.md @@ -0,0 +1,73 @@ +--- +title: The Web +--- + +You're probably already used to navigating websites, downloading and using apps or playing games. Everything you do online is internconnected. But do you know how and why everything works the way it does? We'll try to go through the basics, and you'll be able to dive deeper as needed. + +![An abstract image showing the possible interior of an internet cable.](/internet-abstract.jpg) + +The internet is, while oversimplified, just a bunch of computers connected to a shared *network* over which they are communicating. Just like we right now communicate in English, a common language we both understand, the same way all the participants in the network communicate using [protocols](https://www.cloudflare.com/learning/network-layer/what-is-a-protocol/). + +Furthermore, similarly to how we exchange messages vocally or through text, the same way computers make [requests](/backend/requests) and *can receive* [responses](/backend/requests) unsing said protocols as a common language that is understood by all parties in the information exchange. The messages sent over the internet range from short texts to large files such as videos or photos. To send these messages easily and reliably over the internet we break them up into small [packets](https://www.cloudflare.com/learning/network-layer/what-is-a-packet/), which are then reassembled by the receiver. + +We don't, however, refer to participants on the internet as *computers*. We rather refer to them generically as **clients** and **servers**. We'll most commonly refer to a client as the end-user's device, browser, or computer. Servers on the other hand are, basically, software systems that typically **receive requests** from clients, do something based on the request contents and then, maybe, **send back a response**. We usually refer to this type of communication as [client-server](https://en.wikipedia.org/wiki/Client%E2%80%93server_model), however realistically, most communication on the internet is [inter-server](https://en.wikipedia.org/wiki/Inter-server) (sometimes also referret to as machine-to-machine). + +> [!tip] Exercise! +> +> Now that you know on a high-level how the internet works, try coming up with a list of examples for clients and servers! + +## Networks + +A network is, simply put, a group of computers that can communicate with each other. All of these networks combined make up the internet, and computers in different networks can communicate with each other because of some simple rules that were put in place. + +For two computers to communicate they need to be able to find each other. To do this they need a so called [IP Address](https://en.wikipedia.org/wiki/IP_address). When a client makes a request to a server they first need to know where to send that request to. A typical IP address looks like `3.87.9.125`, this is a so-called IP version 4 address (IPv4), and as you can see, it's not that easy to remember. You may have also hear of IPv6, those are [even weirder](https://en.wikipedia.org/wiki/IPv6)! + +### The Domain Name System (DNS) + +Don't know about you, but I can barely remember my phone number, why would I remember some random IP address? That's where the DNS comes in. The DNS is like the phonebook of the internet. A domain is a human-readable text that represents an IP. For example, `google.com` is actually `142.250.191.78` (depending on where you live, but we won't get into that). + +We call the above [domain name](https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name/) - IP relationship as an Alias, also called an "A record". As I told you earlier, the DNS is like a phonebook, and in this phonebook we call `com` a Top Level Domain (TLD). `google` is a subdomain of the `com` TLD, however the first subdomain is usually referred to as an Apex domain. + +Anyone can buy a domain, most often the domain you buy is an Apex domain. Once you own that domain, you can do all kinds of configurations on the DNS. These configurations are called [Records](https://www.cloudflare.com/learning/dns/dns-records/), and you can have as many as you want, the most common one being A records. Other records have other designations. For instance, an MX record is used for Mail Exchange, so an email server knows that the `johhny@gmail.com` email should be sent to the `gmail.com` servers. Other types of records include `TXT`, `CNAME`, `AAAA` (`A` but for IPv6), etc. + +The most important type of DNS record is `NS`, otherwise called [Nameservers](https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/). You see, the DNS is a democratic system. There isn't just one global server that manages all addresses of all servers. There are actually many DNS servers around the globe that keep track of all domains and their DNS records. The `NS` record basically says which one of all of these DNS servers is your "home" one. When you add a new DNS record it first gets recorded on your Nameserver. You'll probably notice that your shiny new domain doesn't yet work. That's because the domain name is only present on the DNS of your provider, but not on the DNS of your ISP. Therefore, it usually takes a bit of time until the changes in your domain are *propagated* to other DNS servers in the world (there are [tools online](https://www.google.com/search?q=dns+propagation) to check this process). + +> [!tip] Getting your first domain +> +> You don't need to pay for a domain. Try getting a [free .me domain](https://nc.me/)! + + +### Public & Private IPs + +You may have heared before the phrase "dynamic IP" when talking with your friends about your home internet. This term is also usually accompanied by "static IP". But why's that? Isn't the point of the internet that all computers communicate with each other? Yes but also no. + +You see, while you want your computer to access the internet, you most probably *don't want* the internet to access your computer. You computer per se does not have a public IP, if you run `ipconfig` in the command line in Windows, you'll probably notice something like: + +```sh +Wireless LAN adapter Wi-Fi: + Connection-specific DNS Suffix . : + Link-local IPv6 Address . . . . . : fe80::bce6:96bb:9647:c541%3 + IPv4 Address. . . . . . . . . . . : 192.168.0.10 * + Subnet Mask . . . . . . . . . . . : 255.255.255.0 + Default Gateway . . . . . . . . . : 192.168.0.1 +``` + +I've marked the most important lines with an asterisk. You'll notice that your IPv4 address is something like `192.168.0.*` (depending on your router it can also look like `172.16.*.*` or `10.*.*.*`). This is a [private IP](https://en.wikipedia.org/wiki/Private_network), and it **cannot** be accessed from the internet. While on the internet each public server has a public IP that can be reached by anyone, your local network is managed by your router, and it assigns each device on the network an IP that is unique in that specific network. + +This setup is usually used with servers as well. Typically there is one server that has a public IP, and that server is tasked with forwarding incoming requests to the correct server. You can think of this process like a waiter at a restaurant. The waiter is the public facing server, and the chef and the other kitchen staff are private servers who receive the orders from the chef. + +### Ports + +Similar to how a school has a single address but multiple entrances, a server has an IP and can send and receive requests on a `port`. This can more easily be explained using an example. + +Let's say you are hosting a website that can be access at the [URL](/fundamentals/the-url) `http://mywebsite.com`. The two most important components of this URL are the protocol (`http:`) and the domain name (`mywebsite.com`). To access the website, the domain name must point an A record towards the server your website is hosted on, and your server must be able to accept connections over the `http` protocol. By convention, HTTP requests use the port 80 for communcation, so the packets sent to request the website contents would be sent to `3.87.9.125:80`. Other protocols use other ports. For instance, `https` uses port 443, email servers typically use a combination of 25, 587 or 465. Of course, no one stops you if you want to use other ports, but common protocols use established, well-known ports to be able to communicate effectively and reliably. + +## Protocols + + + +### TCP/IP + + + +### HTTP/S \ No newline at end of file diff --git a/content/images/internet-abstract.jpg b/content/images/internet-abstract.jpg new file mode 100644 index 00000000..e8d1055f Binary files /dev/null and b/content/images/internet-abstract.jpg differ diff --git a/content/images/quality-triangle.svg b/content/images/quality-triangle.svg new file mode 100644 index 00000000..3a915095 --- /dev/null +++ b/content/images/quality-triangle.svg @@ -0,0 +1,117 @@ + + + + + + + + + image/svg+xml + + + + + + + TIME + COST + SCOPE + QUALITY + + diff --git a/content/index.md b/content/index.md new file mode 100644 index 00000000..352d295b --- /dev/null +++ b/content/index.md @@ -0,0 +1,23 @@ +--- +title: The Webamboos Guidebook +--- + +Welcome! Glad you found your way to our Guidebook. You may be asking what you'll find here, and we'll gladly answer that curiosity. We are big advocates of [lifelong learning](https://en.wikipedia.org/wiki/Lifelong_learning), so we decided to create and share some sort of learning resource for newbies and veterans alike in the web community. + +## ⭐ A brief introduction + +The **Webamboos Guidebook** is a collection of learning resources. As the web is vast and the technology advances quickly, we want to build a good knowledge foundation for everyone trying to get into web development, but also software engineering as a whole. + +While the guidebook is written for beginners, our philosophy does not exclude practicants with years of experience, we want to write interesting information for everyone. You never know what hidden gems you'll find! + +> [!tip] Tip! +> +> **Go explore!** Learning is not linear, not even this guidebook. *Please*, click through all the links you find, try to build your own mental model of all the knowledge you can get. When you get back to a topic, everything will feel familiar! + +Before delving into technical information, we'll first visit the [the Mindset](/mindset/problem-solving). We'll show you why an engineer is a *problem solver*, how he takes decisions and why factors other than code need to be taken into account when creating new solutions. + +In the second chapter of the Guidebook you'll jump into the [Fundamentals](/fundamentals/the-web). Everything is interconnected (also why we chose to show you the nice graph on the side), having a good grasp of the fundamentals will allow you to go way beyond just the basics. Understanding the building blocks will show you how simple the web actually is. + +Chapter three introduces the first actual technical challenges, and we'll start by building a simple [Backend](/backend/servers) server. This chapter will show you how to build a simple server, how to handle [requests](/backend/requests), [responses](/backend/requests#responses), connecting and using a [database](/backend/databases), and more. + +Todo. \ No newline at end of file diff --git a/content/mindset/index.md b/content/mindset/index.md new file mode 100644 index 00000000..abc02f43 --- /dev/null +++ b/content/mindset/index.md @@ -0,0 +1,4 @@ +--- +title: Mindset +--- + diff --git a/content/mindset/knowledge-portfolio.md b/content/mindset/knowledge-portfolio.md new file mode 100644 index 00000000..710bf13c --- /dev/null +++ b/content/mindset/knowledge-portfolio.md @@ -0,0 +1,3 @@ +--- +title: Your knowledge portfolio +--- \ No newline at end of file diff --git a/content/mindset/problem-solving.md b/content/mindset/problem-solving.md new file mode 100644 index 00000000..06628a77 --- /dev/null +++ b/content/mindset/problem-solving.md @@ -0,0 +1,49 @@ +--- +title: Problem Solving +--- + +As a programmer you will be faced with many challenges throughout your career. From stubborn clients who don't know what they want but they want it yesterday, to colleagues who have been struggling with a build issue for two days, all being problems that require solving. + +There is no definitive solution to any problem, but there are *good enough* solutions that you can come up with in the shortest amount of time that will satisfy, in one way or another, the other party. + +> [!tip] The 80/20 Rule +> Also known as [the Pareto Principle](https://en.wikipedia.org/wiki/Pareto_principle), states that 80% of the consequences come from 20% of the causes. This is a good rule of thumb to use in any problem solving situation to determine whether the amount of effort is worth it or not. For instance, if we can build 80% of a feature with ony 20% effort, then that is a good trade. + +Finding the right solution at the right time is not easy, and it certainly won't occur to you all the time, but actively tring to find solutions to the problems you encounter will make it easier with time. "*But how do I find the right solution?*", you might ask. The answer to that is the classic: *it depends*. + +### The root cause + +Many times people come to us asking for solutions to their problems. An issue with that is the lack of context they usually provide, this is one of the reasons you'll hear the answer "it depends" when senior developers respond to the question "how long will this take to build". Without enough context, solutions can range from simple but ineffective, to complex and costly, while still not solving the problem. People may even ask for solutions to the wrong problems. + +Every problem is caused by something. Finding that *something* can be quick and easy, or tiresome and hard. In such situations, as developers, we need to start asking questions and exploring the mind of the people looking for solutions. A good technique is the ["5 whys"](https://en.wikipedia.org/wiki/Five_whys). Finding the root cause can lead to better and more sustainable solutions (and sometimes much easier), fixing problems right where they appear, instead of trying to fix the symptoms. + +### Finding constraints + +Maybe you need to improve the performance of a search algorithm, or maybe you are working with Big Data and need to integrate an ETL pipeline to find temperature anomalies in the thousands of warehouses of this ice-cream factory. No matter what the problem, there are always some constraints that you need to find. + +You may have heard of the "project management triangle" (or other variations), but if not, you have now. + +
+ +![[quality-triangle.svg|A triangle with the words "Scope", "Cost" and "Time" in each corner, and "Quality" written in the middle.]] + +
The Project Management Triangle
+
+ +The triangle is most often used in project management, but it can also be used for problem solving. Every project has some constraints, and they are usually either time, cost, or the scope(amount of features required). You cannot have a high quality project, built cheaply and timely, so you'll need to find the best trade-offs. If a client needs both a high-quality product and fast, then they need a lot of money to throw at the problem. + +Most often though, the client doesn't have the money, or the time. So we need to find the best balance. We can reduce the scope (i.e. build fewer features), so we can ship faster and cheaper. Or, we can build all the features, but then the quality takes a hit (but we want to avoid that, because developers don't like to build poor quality things). In the end, it's all trade-offs, so you need to be able to adapt to the problem at hand, and, most importantly, [communicate](#communicating-solutions). + +### Communicating solutions + +You are never alone. While many programming problems can be solved quickly, without much (if any) input from others, most problems usually involve more that just the few lines of code around the current file. + +Let's say you need to build a password reset mechanism. You know that you need to send emails with the password reset link, but you don't have an email service you can use. You also need to take into account that your system will probably send many other types of emails, such as notifications or newsletters. Immediately, the problem becomes slighly more complex. Maybe the newsletters will be sent by the client using a visual editor, or the notifications will also be sent as SMS or as push notifications. + +Suddenly you need to find a service that can handle all of these (or multiple services). However, these services usually cost money, you won't use your own money for that, but the clients'. You could just tell them what you need, but they won't know what to do and they won't understand why they need to pay. That's where you come in. + +Usually problems have multiple possible solutions, it's your job to find the best solutions taking into account the [constraints](#finding-constraints) and present them to the team and/or the client. This might involve a document (or just a Slack message) outlining the problem, possible solutions (their benefits, costs, risks, etc.), future predictions (e.g., a more expensive solution could solve problems that might arise in the future), and your personal recommendation (and why). This won't only make it easier for other stakeholders to take the *right decisions based their needs*, but it also proves that you are *trustworthy*, did the required research and that you really are interested in the best possible solutions for the product under development. + +### Being proactive + +Todo. diff --git a/content/mindset/why.md b/content/mindset/why.md new file mode 100644 index 00000000..6f15f140 --- /dev/null +++ b/content/mindset/why.md @@ -0,0 +1,11 @@ +--- +title: Why it all matters +--- + +You might have expected a more technical guide, do this, build that, show here. But that's not what this guidebook is, and that's not what a developer does. + +In short, the two guiding principles of this guide are: +- The engineering mindset; +- Building of a good foundation. + +Firstly, as developers we don't only sit and execute, but we need to understand problems, needs of the target userbase, manage expectation, communicate, collaborate, make decisions, and take the best possible approach when designing and building new solutions. \ No newline at end of file diff --git a/content/resources/index.md b/content/resources/index.md new file mode 100644 index 00000000..55d19830 --- /dev/null +++ b/content/resources/index.md @@ -0,0 +1,3 @@ +--- +title: Resources +--- \ No newline at end of file diff --git a/content/the-company/about.md b/content/the-company/about.md new file mode 100644 index 00000000..a77c3bec --- /dev/null +++ b/content/the-company/about.md @@ -0,0 +1,5 @@ +--- +title: About us +--- + +About us \ No newline at end of file diff --git a/content/the-company/index.md b/content/the-company/index.md new file mode 100644 index 00000000..86ae35fd --- /dev/null +++ b/content/the-company/index.md @@ -0,0 +1,3 @@ +--- +title: The Company +--- diff --git a/package-lock.json b/package-lock.json index 8ef3e9f0..e5a93287 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,7 +74,7 @@ "@types/d3": "^7.4.3", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", - "@types/node": "^20.11.29", + "@types/node": "^20.11.30", "@types/pretty-time": "^1.1.5", "@types/source-map-support": "^0.5.10", "@types/ws": "^8.5.10", @@ -1170,9 +1170,9 @@ } }, "node_modules/@types/node": { - "version": "20.11.29", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.29.tgz", - "integrity": "sha512-P99thMkD/1YkCvAtOd6/zGedKNA0p2fj4ZpjCzcNiSCBWgm3cNRTBfa/qjFnsKkkojxu4vVLtWpesnZ9+ap+gA==", + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index f785b4b3..9b854fdc 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "@types/d3": "^7.4.3", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", - "@types/node": "^20.11.29", + "@types/node": "^20.11.30", "@types/pretty-time": "^1.1.5", "@types/source-map-support": "^0.5.10", "@types/ws": "^8.5.10", diff --git a/quartz.config.ts b/quartz.config.ts index 4b98325d..ebed97fb 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -8,22 +8,20 @@ import * as Plugin from "./quartz/plugins" */ const config: QuartzConfig = { configuration: { - pageTitle: "ðŸŠī Quartz 4.0", + pageTitle: "The Guidebook", enableSPA: true, enablePopovers: true, - analytics: { - provider: "plausible", - }, + analytics: null, locale: "en-US", - baseUrl: "quartz.jzhao.xyz", - ignorePatterns: ["private", "templates", ".obsidian"], - defaultDateType: "created", + // baseUrl: "guidebook.webamboos.com", + ignorePatterns: ["private", "templates", ".obsidian", "docs"], + defaultDateType: "modified", theme: { fontOrigin: "googleFonts", cdnCaching: true, typography: { - header: "Schibsted Grotesk", - body: "Source Sans Pro", + header: "Onest", + body: "Onest", code: "IBM Plex Mono", }, colors: { @@ -33,19 +31,19 @@ const config: QuartzConfig = { gray: "#b8b8b8", darkgray: "#4e4e4e", dark: "#2b2b2b", - secondary: "#284b63", + secondary: "#222222", tertiary: "#84a59d", highlight: "rgba(143, 159, 169, 0.15)", }, darkMode: { - light: "#161618", + light: "#0f0f0f", lightgray: "#393639", gray: "#646464", darkgray: "#d4d4d4", dark: "#ebebec", - secondary: "#7b97aa", + secondary: "#eeeeee", tertiary: "#84a59d", - highlight: "rgba(143, 159, 169, 0.15)", + highlight: "rgba(143, 159, 169, 0)", }, }, }, @@ -54,7 +52,9 @@ const config: QuartzConfig = { transformers: [ Plugin.FrontMatter(), Plugin.CreatedModifiedDate({ - priority: ["frontmatter", "filesystem"], + // you can add 'git' here for last modified from Git + // if you do rely on git for dates, ensure defaultDateType is 'modified' + priority: ["frontmatter", "filesystem", "git"], }), Plugin.Latex({ renderEngine: "katex" }), Plugin.SyntaxHighlighting({ diff --git a/quartz.layout.ts b/quartz.layout.ts index b5a1639e..7e633c48 100644 --- a/quartz.layout.ts +++ b/quartz.layout.ts @@ -7,12 +7,56 @@ export const sharedPageComponents: SharedLayout = { header: [], footer: Component.Footer({ links: { - GitHub: "https://github.com/jackyzha0/quartz", - "Discord Community": "https://discord.gg/cRFFHYye7t", + "webamboos.com": "https://webamboos.com", + GitHub: "https://github.com/webamboos", + LinkedIn: "https://linkedin.com/company/webamboos", + Facebook: "https://www.facebook.com/webamboos", + Instagram: "https://www.instagram.com/webamboos", }, }), } +function explorer () { + return Component.Explorer({ + sortFn(a, b) { + const nameOrderMap: Record = { + "mindset": 100, + + "fundamentals": 200, + "the-web": 201, + "the-url": 202, + "javascript": 203, + "development-environment": 204, + "package-management": 205, + + "backend": 300, + "frontend": 400, + "advanced": 500, + "best-practices": 600, + "resources": 700, + "the-company": 800, + } + + let orderA = 0 + let orderB = 0 + + if (a.file && a.file.slug) { + orderA = nameOrderMap[a.file.slug] || nameOrderMap[a.name] || 0 + } else if (a.name) { + orderA = nameOrderMap[a.name] || 0 + } + + if (b.file && b.file.slug) { + orderB = nameOrderMap[b.file.slug] || nameOrderMap[b.name] || 0 + } else if (b.name) { + orderB = nameOrderMap[b.name] || 0 + } + + return orderA - orderB + } + }) +} + // components for pages that display a single page (e.g. a single note) export const defaultContentPageLayout: PageLayout = { beforeBody: [ @@ -26,7 +70,7 @@ export const defaultContentPageLayout: PageLayout = { Component.MobileOnly(Component.Spacer()), Component.Search(), Component.Darkmode(), - Component.DesktopOnly(Component.Explorer()), + Component.DesktopOnly(explorer()), ], right: [ Component.Graph(), @@ -43,7 +87,7 @@ export const defaultListPageLayout: PageLayout = { Component.MobileOnly(Component.Spacer()), Component.Search(), Component.Darkmode(), - Component.DesktopOnly(Component.Explorer()), + Component.DesktopOnly(explorer()), ], right: [], } diff --git a/quartz/components/ExplorerNode.tsx b/quartz/components/ExplorerNode.tsx index 2968a03e..5ccc29fd 100644 --- a/quartz/components/ExplorerNode.tsx +++ b/quartz/components/ExplorerNode.tsx @@ -188,7 +188,9 @@ export function ExplorerNode({ node, opts, fullPath, fileData }: ExplorerNodePro // Node with entire folder // Render svg button + folder name, then children
- + + {/* - + */} {/* render tag if folderBehavior is "link", otherwise render