Skip to content

Latest commit

 

History

History
535 lines (378 loc) · 26.1 KB

README.md

File metadata and controls

535 lines (378 loc) · 26.1 KB

JavaScripted

JavaScripted original logo.

JavaScripting y'all

React TailwindCSS TypeScript Astro

🐱 /JuditKaramazov

📍 Portfolio

☕ Blog


Table of Contents


🔧 Getting started

Frameworks, libraries, constant changes, improvements, failures, stories of success... Some things never die, though - like my love story with Astro's developer-friendly features and flexibility, TypeScript and its type safety, or the beautiful React, always covering my astronaut's back with dynamic interactivity and reusable components... Am I getting old? Did I simply find what could potentially be the end of me? Whatever the case: Yes, indeed. Here we go again, fellow Skytroopers!

Just in case you'd want to get started with Astro and its impeccable results, allow me to say that doing so couldn't be easier - and I'll show you why, right here, right now. Step by step, though!

First, open your terminal and run the following command:

npm create astro@latest

Don't forget that you'll find Starter Templates, too:

# create a new project with an official example
npm create astro@latest -- --template <example-name>

# create a new project based on a GitHub repository’s main branch
npm create astro@latest -- --template <github-username>/<github-repo>

Finally:

npm run dev

🚀 Project Structure

If you are interested in playing with my own project, remember that you can always clone the repository:

$ git clone https://github.com/JuditKaramazov/JavaScripted.git
JavaScripted sample.

In this particular case, you'll find the following folders and files:

/
├── public/
│   └── favicon.ico
│   └── fonts
│   └── img
│   └── meta
├── src/
│   ├── components/
│   │   └── Button.astro
│   ├── layouts/
│   │   └── Layout.astro
│   ├── pages/
│   │   └── index.astro
│   ├── sections/
│   │   └── Home.astro
└── package.json

Astro looks for .astro or .md files in the src/pages/ directory. Each page is exposed as a route based on its file name.

There's nothing special about src/components/, but that's where I usually like to put any of my Astro/React/Svelte components.

Any static assets, like images, can be placed in the public/ directory. Ask Vercel about it!

🧞 Commands

Finally, remember that all commands are run from the root of the project, from a terminal:

Command Action
npm install Installs dependencies
npm run dev Starts local dev server at localhost:3000
npm run build Build your production site to ./dist/
npm run preview Preview your build locally, before deploying
npm run astro ... Run CLI commands like astro add, astro check
npm run astro --help Get help using the Astro CLI

Easy, right? Feel free to check Astro's documentation or jump into their Discord server. Enjoy the ride, dear astronaut! 🚀🧑‍🚀

Tip

Whatever you decide to do, please remember to respect the Code of Conduct while interacting with the project and the platform itself. Thank you kindly!


🚪 Introduction

Not so long ago, while having a look at my old notebooks, I found a bunch of them dedicated to JavaScript exclusively. In all honesty, it sent chills down my spine; although it feels like it's been ages since I started struggling with all these programming concepts and headaches, the truth is that I immersed myself into this universe in "recent" times. Jumping into the unknown - what a concept for someone who spent so many years exploring the void and unveiling the multifaceted nature of emptiness.

That's perhaps the right word: "Emptiness". While mystical intelligence becomes an open window into such a heavy-weighted concept, this "emptiness" is exactly what I felt while turning pages and pages filled with notes, diagrams, and code snippets. "Never forgive, never forget", yet the sudden urge to keep those memories intact made me feel that I had to "react" (ha, ha), fast and furious style.

If it was helpful for me, perhaps it could be useful for someone else, right?

JavaScripted screenshot.

As some of you probably know, I started a multilayered project focused on a very simple idea: Sharing legally and freely for better learning must be a priority, as the lack of universal access to effective educational resources remains a global problem. Inevitably, although I already wrote chapters and chapters discussing online websites, books, lists of free, online, and certified learning resources, or courses and cheatsheets that I myself prepared, I had to find some space for the language that started it all before Python put several concepts in their rightful place: JavaScript.

That's why JavaScripted exists: "Once a teacher, always a teacher", and this modern collection of JavaScript notes on several topics totally communicates this teacher mindset I can't get rid of.

These days, learning has become not only a need but a reasonable reality; if you have access to an internet connection, you are good to go. It's not always so simple to find the materials appropriately accommodated to our personal way of learning, though, and even though you'll encounter better JavaScript notes, code snippets, and interactive templates out there, why wouldn't I share mine?

They might become someone else's lighthouse when everything is perceived as wrong, heavy, and purposeless...


🔮 Features

Lighthouse-score

... But speaking of lighthouses! It seems I'm consecutively getting worse and worse at keeping my "Best Practices" in good shape, but there's always room for improvement!

Just like everything I've been developing lately, I tried my best to keep JavaScripted simple, clean, accessible, and still as performant and updated as possible, though. Undoubtedly, Astro played a huge part in it, yet I won't deny that sometimes (just sometimes, guys. Don't overestimate me), I find myself scratching (and mostly, breaking) my head in order to come up with the best practices and ideas.

"What did you do this time, Judit? Thank you for asking, inexistent interlocutor! Let's see the terrible 🔥m e s s🔥 that I created this time in detail.

🌐 Accessible

I won't deny that I'm still a freshman with whatever has to do with the concept of Accessibility. However, I consider it essential to shift our mindset and view this idea as an integral part of the development process rather than an afterthought, and thanks to what I learned in previous projects, you'll be capable of navigating JavaScripted by using:

  1. Keyboard 💻
  2. VoiceOver 🎙️

Tip

Remember that you can turn on VoiceOver on an iPhone running IOS 17 or later. This can be done from settings -> Accessibility -> VoiceOver.

🎭 Custom theme for code snippets

It might sound like a fairytale written by an excentric man dressed as a dwarf, but back in the day, I created some Visual Studio Code custom themes based on Evangelion's aesthetics, which you can find either in the Marketplace, either in my EVASCode dedicated repository. Guess what? Yes, indeed: She did it again!

Although I won't deny the process might be tedious, the results are quite neat:

JavaScripted code snippet.

Ah, but before achieving such results... The theme itself includes:

  • Dark theme: Custom dark theme designed for readability and minimal eye strain.

  • Semantic Highlighting: Special token coloring for enums, constants, operators, and functions.

  • Token Colors:

    • Enums, constants, and default libraries.
    • Math-related properties.
    • Function parameters and punctuation.
    • Logical and bitwise operators.
    • Keywords and control elements:.
    • Strings.
  • Support for JS/TS: Enhanced token support for JavaScript and TypeScript, including syntax for imports, functions, modules, and console statements.

  • Preload Fonts: Optimized for web performance by preloading custom fonts for better visual aesthetics.

If you're the curious type and would want to see more about it, don't hesitate to have a look at:

🎨 Dynamic OG image generation

Little reminder time: OG ("Open Graph") images are the social pictures displayed whenever we share our website URL on platforms such as Twitter, WhatsApp, Discord, etc., and guess what? They help your content stand out, attract clicks, and encourage engagement. Much to our human, idealist soul, they are an essential part of digital marketing - and we all do love marketing, don't we? Just like we love our repositories to be starr-...

Ahem. So! In order to avoid the static usage of the same image being displayed over and over again, and thanks to both Satori's library and some personal tweaks, it's been possible to generate dynamic OG images at build time for each lesson or section of JavaScripted, now featuring:

  1. Site title.
  2. Some self-love.
  3. Lesson's title.
  4. Lesson's description.

JavaScripted OG image.

Thanks to the SVG generation with Satori, the dynamic font handling, and the asynchronous nature of reading files and filtering .mdx files... boom! Easy peasy, as you'll see for the latest example:

const dir = "./src/content/lessons"; // Defines content directory.
try {
  const files = await readdir(dir); // Reads all files in the directory.
  const logo = await readFile(
    new URL("./public/img/icons/javascripted-logo.svg", import.meta.url),
    {
      encoding: "base64",
      width: 300,
      height: 44,
    }
  );

  for (const file of files) {
    if (extname(file) !== ".mdx") {
      continue; // Skips non-mdx files.
    }
    
    const content = await readFile(join(dir, file), "utf8");
    const result = matter(content); // Extracts frontmatter.
    
    await generateOgImage({
      title: result.data.name,
      slug: result.data.name.toLowerCase(),
      description: result.data.tagline,
      logo,
    });
  }
} catch (err) {
  console.error("Error:", err);
}

Although this is not difficult to integrate at all, please feel free to check the code for further information:

📦 Codesandbox-ed

A picture is worth a thousand words - now imagine the value of embedded sandboxes! As mentioned above, my notes were handwritten ones, meaning that in many cases, I had to draw entire components and deglosse their behavior just so that my mind could process what was supposed to happen when running a specific chunk of code. No more wild imagination is required, though.

Codesandbox, as many of you will definitely know, provides instant development environments that get you up and running quickly and keep you in flow. Why is this relevant? Because the programming field is imminently practical, and visualizing and interacting with prototypes felt like the best option in most cases:

JavaScripted code preview.

By combining static code snippets with code previews, the learning experience might become way more pleasant, clear, and enjoyable.

As an example of the integration, let's check what happened in the .mdx file regarding Scopes:

---
name: Scopes
rank: 4
tagline: Scope refers to the context in which variables are declared and can be accessed.
ogImage: scopes
sandboxId: rxpfnn
previewHeight: 500px
relatedLesson:
  - hoisting
---

import CodePreview from "../../components/CodePreview.astro";

// ...

<CodePreview
    sandboxId={frontmatter.sandboxId}
    previewHeight={frontmatter.previewHeight}
/>

// ...

There you go! The result translates into the above image: relevant explanations combined with interactive components.

For further information about this specific feature and the Codesandbox integration, please, have a look at:

and

For instance, here's how easy it gets to become a digital cat:

utils.ts
--------
import { SandpackFile } from "@codesandbox/sandpack-react";

export async function getFiles({ id }: { id: string }) {
  const configUrl = `https://codesandbox.io/api/v1/sandboxes/${id}/sandpack`;
  const response = await fetch(configUrl);
  if (response.ok) {
    const data = await response.json();

    return updateFiles(data.files);
  }
  return {};
}

function getChallengeConfig(json: string) {
  const csb = JSON.parse(json);

  if (csb?.previewConfig) {
    return csb.previewConfig;
  }

  return {
    visibleFiles: [],
    activeFile: "/src/App.js",
  };
}

export function updateFiles(files: { [key: string]: SandpackFile }) {
  const previewConfig = getChallengeConfig(files["/package.json"].code);
  Object.keys(files).map((key) => {
    if (key === previewConfig.activeFile) {
      files[key].active = true;
    }
    if (!previewConfig.visibleFiles.includes(key)) {
      files[key].hidden = true;
    }
  });
  return files;
}

I didn't lie when I said it's a piece of cake, guys!

🕸️ Interconnected

Although many of you probably realized there's some sort of interconnectivity included directly in the frontmatter, JavaScripted includes not only a marquee showcasing all available lessons after finishing each note (as well as some relevant documentation), but also a "Related notes" section directly sending you to some content-related topics:

JavaScripted Related notes screenshot.

The easiest, the better!

🧅 Multilayered

What's perhaps not so easy is adding an onion emoji representing a multilayered reality, though (they have... tons of layers to remove, if you think of it).

Independently of that, and as stated above, JavaScripted works as part of two other projects of mine:

Pythomazov original logo.

Feel free to check them now that the family's getting bigger! And don't forget that everything is connected under the Iris, no matter the corner of the interwebz you're hiding at!

🔒 Privacy-oriented

This might surprise some of you, but no: I am not a maniac, and yes: I do care about your privacy.

That's why, and as you'll see if you decide to check this site's Layout.astro, I decided to implement Umami, a lightweight, simple, open-source, and privacy-focused analytics solution. Long story short, it provides you with insights about your website traffic (such as page views, referral sources, and visitor behavior) while prioritizing user privacy, which means:

  • No cookies, guys (if we were talking about real ones, I would understand some sadness). Umami is GDPR (General Data Protection Regulation), CCPA (California Consumer Privacy Act), and PECR (Privacy and Electronic Communications Regulations) compliant by default. This leads to...

  • No tracking consent banners needed.

  • No personal data collection.

Tip

If you are looking for some transparency and ethical alternatives to big tech while having a minimal impact on website performance, I suggest you try! Don't forget to read their documentation first, though. That's always essential.

🤝 SEO-friendly

What we call "SEO-friendly content" is the type of content that's created in a way that helps the search engines rank it high - and no, it's not all about keywords, as you might have noticed. Actually, "SEO" is meant to help search engines find, understand, and connect your content to the topic you're trying to cover, just like we saw previously while discussing the dynamic ogImage concept.

If we pay attention to our src/layouts/Layout.astro:

---
import "../styles/globals.css";
export interface Props {
  title: string;
  description: string;
  ogImage?: URL;
  url?: URL;
}

const {
  title,
  description,
  ogImage = new URL("/meta/og.jpg", Astro.url),
} = Astro.props;

const pathname = Astro.url.pathname;

const url =
  pathname[pathname.length - 1] === "/"
    ? new URL(pathname.slice(0, pathname.length - 1), Astro.site)
    : new URL(Astro.url.pathname, Astro.site);
---

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
    <link rel="manifest" href="/site.webmanifest">
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
    <meta name="msapplication-TileColor" content="#da532c">
    <meta name="theme-color" content="#ffffff">
    <meta name="generator" content={Astro.generator} />
    <title>{title}</title>
    <meta name="description" content={description} />
    <meta name="author" content="Judit Lázaro Moyano" />
    <meta property="og:type" content="website" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:site" content="@v_karamazov" />
    <meta name="twitter:creator" content="@v_karamazov" />
    <meta
      content={description}
      name="twitter:description"
      property="og:description"
    />
    <meta name="twitter:title" property="og:title" content={title} />
    <meta property="twitter:url" content={url} />
    <meta name="twitter:image" content={ogImage.href} />
    <meta property="og:url" content={url} />
    <meta property="og:title" content={title} />
    <meta property="og:image" content={ogImage.href} />
    <meta property="og:description" content={description} />
    <link rel="canonical" href={url} />

    // ...

We will see that the layout integrates several SEO-friendly elements:

  • proper meta tags,

  • Open Graph and Twitter Cards,

  • canonical links,

  • mobile optimization,

  • performance optimizations...

All of these elements are key if we want to make our site easily crawled and indexed by search engines, so don't hesitate to have a full look at the code in order to learn more!


💄 Style

And the award goes to...

JavaScripted main, screenshot.

As usual, mentioning the amazing artists out there (thank you for your incredible work - and also for making it free and available for everyone!) or noting down the several tools and applications that I used doesn't truly translate into the human work behind building a website. Don't get me wrong: it means a lot, but "a lot" pales in front of the bigger picture.

It took time. Moreover, this project forced me to play "Tumbling Lights", by The Acid loop-style in order to stay awake and finish gathering the notes, examples, and ideas I had in mind. When it started looking better, it felt wrong. Then, it wasn't enough. Never enough. Remarkably, if I had to highlight something about the aesthetic lines that I drew here, I would simply say that I purposely chose a dark theme to represent how pessimistic it all became when I was trying to convince myself that I wasn't capable of coding. There was light, too, sometimes; that's what the vibrant colors represent.

These tumbling lights also imply the presence (even though you might call it an absence) of AuNedelec throughout the entire process, always encouraging me and letting me know that my head wanted to betray me. Perhaps we didn't get to explicitly collaborate this time, but deep inside, you have always been the best collaborator I ever had.

Thank you kindly - and bear in mind that I'll surely keep you occupied with my little apps and projects in Grenoble! 🫂


🙌 Immense thanks to them awesome Sponsors

Los jugadores son mis amigos. Now, I refuse to start writing this section in a different tone, but now that one-of-my-favorite-quotes has been said... let's intone a loud and sincere: Thank you ❤️.

To our amazing Sponsor, @Entreprises LEMRHALI, thank you so much, and sorry for not being physically there now that things feel so overwhelming and harsh. However, let me quote a character that I found extremely touching (yes, the one you have in mind, you little wizard):

So close, indeed. Then I am not entirely alone, just yet. Praise the merciful gods above.

Hay esperanza. And everything will get better soon - you have my word. I can't wait for us to laugh about these distant memories (that's what they'll become, believe me) while exploding some kittens. Until then: courage, patience, and remember that you are not alone.

Visual asset of a pixel-art weapon rack.


🏛 License & Copyright

This work lives under the robust, solid, beautiful, and probably scripted roof of the MIT License; whatever visual or written content scapes from it, you'll always find a proper reference specifying the authors and websites behind.

Attributions are essential these days, and whoever took part directly or indirectly in this project deserves the best possible recognition. That said, and only if you enjoyed what you found here, remember that you can make the Dinosaur extremely happy if you...


Buy Me A Coffee