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..6654752b --- /dev/null +++ b/content/fundamentals/the-web.md @@ -0,0 +1,4 @@ +--- +title: The Web +--- + 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..51471d2c --- /dev/null +++ b/content/index.md @@ -0,0 +1,21 @@ +--- +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. \ 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 7e71a1d3..fb99c0af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,7 +73,7 @@ "@types/d3": "^7.4.3", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", - "@types/node": "^20.11.19", + "@types/node": "^20.11.25", "@types/pretty-time": "^1.1.5", "@types/source-map-support": "^0.5.10", "@types/ws": "^8.5.10", @@ -1093,9 +1093,9 @@ } }, "node_modules/@types/node": { - "version": "20.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", - "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" diff --git a/package.json b/package.json index ef623a0f..05ec1f53 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "@types/d3": "^7.4.3", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", - "@types/node": "^20.11.19", + "@types/node": "^20.11.25", "@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 2cdadb74..8a5b492f 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -8,21 +8,19 @@ 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: { cdnCaching: true, typography: { - header: "Schibsted Grotesk", - body: "Source Sans Pro", + header: "Onest", + body: "Onest", code: "IBM Plex Mono", }, colors: { @@ -32,19 +30,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)", }, }, }, @@ -53,7 +51,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