Solidifying my Weekly Review Template has been extremely useful. It reminds me what’s important and what’s not, and putting the reasoning as to why I put a task on my weekly review.
I found a YouTube short about this woman who lost her job, and her reaction was to be happy. Like of course it’s going to garner views, and she even admits it’s not the normal reaction people have to being fired.
I’ve become a huge fan of Jillian Hess’ newsletter, Noted. She distills what she’s learned by reading some of history’s favorite note-takers (and contemporary)
For all of these little hacks, I place them in a separate note with the title of the device. Our Crosley record player stopped spinning, and all I had to do was move the needle to the right
A rabbit hole I fell into was the history of the Fillmore in San Francisco, and the legacy of Bill Graham
One thing I was browsing through were the old concert posters for Fillmore West. The psychedelic poster art from Wes Wilson are just phenomenal, especially if you grew up listening to Jefferson Airplane, Janis Joplin, and The Grateful Dead.
Custom GPTs could be to build a technology tree visually connected to an infinite canvas app (parked idea)
“Rencontrer” is a meeting with the new. Remembrance is the comfort of recognition.
— Esther Perel
Last week, I learned there are three curiosity attractors. Curiosity Attractors are the recurring fascinations that you can’t shake, whether active or latent.
Epistemic curiosity refers to your desire to learn about the world and resolve gaps in your understanding
Empathic curiosity relates to your interest in connecting with others, understanding their perspectives and experiences
Diversive curiosity is that fleeting urge you sometimes feel to explore something new just for the sake of novelty, with no clear goal in mind
Curiosity attractors also often intersect with parts of your identity. We go back to questions that fit with our personal values and worldviews
— Anne-Laure Le Cunuff
I learned from Scott H Young that from these three models of learning, the model that appears to be best fit is based off differing prior knowledge. Even for a beginner, they do learn a lot, even if it’s still not as much as someone who came in with a lot of prior knowledge (and they get benefit too)
I have a bunch of files I want to rename using the rename utility.
If you’ve installed the rename utility on your Mac, you can use it to mass rename files in the terminal. The rename utility typically follows a specific syntax, and it’s quite powerful for renaming multiple files according to certain patterns or rules.
Here’s a basic example of how you can use the rename utility:
When dealing with filenames that contain spaces, you’ll need to escape those spaces in your command. Here’s how you can do it using the rename command:
rename 's/ Clear Labs//' *.md
This command will remove the substring ” Clear Labs” (including the space) from all .md files in the current directory.
Over a decade ago, Buster Benson started his "Codex Vitae" or book of beliefs. He started small and re-visited it every year, updating his beliefs as his life changes.
"Morgan Housel shares 19 short stories exploring the strange ways people think about money and teaches you how to make better sense of one of life’s most important topics."
The political and social entanglements of technology in rural China. Their discoveries force them to challenge the standard idea that rural culture and people are backward, conservative, and intolerant. Instead, they find that rural China has not only adapted to rapid globalization but has actually innovated the technology we all use today.
Intro to emotional intelligence (EI) and mindfulness. It goes through mindfulness and meditation exercises to enhance EI, making it relevant for individuals in a modern, fast-paced workplace and lead a happier life.
Svelte is a component-based JavaScript framework that compiles your code at build time rather than at runtime. This means that instead of shipping a bulky framework to the client, Svelte generates highly optimized vanilla JavaScript code that updates the DOM. This approach results in faster load times and better performance. Additionally, Svelte has a small API surface area, making it easy to learn and use.
The following example is a simple counter application that teaches the basics of Svelte.
<script> let count = 0; function increment() { count += 1; } function decrement() { count -= 1; }</script><main> <h1>The count is {count}</h1> <button on:click={decrement}>-</button> <button on:click={increment}>+</button></main><style> main { text-align: center; padding: 1em; } button { margin: 0 1em; padding: 0.5em 1em; }</style>
The count is 0
Reactive Variables: let count = 0; This variable is reactive. Any changes to count will automatically update the DOM wherever count is referenced.
Event Handling: The on:click directive is used to attach click event listeners to both buttons, calling the increment and decrement functions accordingly.
Inline Handlers: If you prefer, you could inline these functions directly in the on:click handler for something even simpler, like on:click={() => count += 1}.
Conditional Rendering: Suppose you want to display a message when the count is above a certain threshold. You can use an {#if} block directly in your HTML:
{#if count > 10} <p>You have reached a count greater than 10!</p>{/if}
Svelte Components
Expanding our simple counter application by breaking it down into smaller components, which is a common practice for improving the organization and reusability of your code in larger applications. We’ll create two components: CounterDisplay for showing the current count and CounterButton for the increment and decrement buttons.
Create a new file named CounterDisplay.svelte in the src directory. This component will be responsible for displaying the count.
<script> // This component accepts a prop named `count` export let count;</script><h1>The count is {count}</h1>
Create another file named CounterButton.svelte in the src directory. This component will represent a button that can increment or decrement the counter.
<script> // The component accepts two props: the button text and the click action export let text; export let handleClick;</script><button on:click={handleClick}>{text}</button>
Now, update the App.svelte file to use these new components.
<script> import CounterDisplay from './CounterDisplay.svelte'; import CounterButton from './CounterButton.svelte'; let count = 0; function increment() { count += 1; } function decrement() { count -= 1; }</script><main> <CounterDisplay {count} /> <CounterButton text="-" handleClick={decrement} /> <CounterButton text="+" handleClick={increment} /></main><style> main { text-align: center; padding: 1em; }</style>
Props: Components in Svelte can accept “props”, which are custom attributes passed into components. In our case, CounterDisplay accepts a count prop, and CounterButton accepts text and handleClick props. This allows the components to be reusable and dynamic. Props are reactive, where any prop changes will trigger changes in the component.
Component Interaction: The App.svelte component manages the state (count) and functions (increment and decrement) and passes them down to the child components. This demonstrates a fundamental pattern of component-based architecture: lifting state up and passing data and behavior down through props.
Event Handling in Child Components: The CounterButton component receives a function (handleClick) as a prop and attaches it to the button’s click event. This is a common pattern for handling events in child components and allowing parent components to define the behavior.
Slots in Svelte
Slots in Svelte allow you to create components that can accept content dynamically from their parents. This is similar to transclusion or content projection in other frameworks. In other libraries like React, this is handled with children. Slots make components more flexible by letting you inject content into predefined places within a component’s template.
Basic Slot Example
Imagine you’re building a Card component that you want to reuse across your application, but with different content each time.
Card.svelte:
<div class="card"> <slot></slot> <!-- This is where the parent's content will be injected --></div><style> .card { border: 1px solid #ccc; border-radius: 8px; padding: 20px; margin: 10px 0; }</style>
You can use this Card component in a parent component and pass in different content like so:
<script> import Card from './Card.svelte';</script><Card> <h2>Title</h2> <p>This is some card content.</p></Card><Card> <p>Another card with different content.</p></Card>
Named Slots
Svelte also supports named slots, which allow you to define multiple slots within a single component.
Card.svelte updated with named slots:
<div class="card"> <header> <slot name="header"></slot> <!-- Named slot for header content --> </header> <slot></slot> <!-- Default slot for main content --> <footer> <slot name="footer"></slot> <!-- Named slot for footer content --> </footer></div>
Module scripts in Svelte introduce a powerful feature for managing reusable code and behaviors in your components. A module script runs once when a component is first imported, rather than each time a component instance is created. This makes it ideal for defining shared logic, helpers, and stores that can be used across all instances of a component.
To define a module script in a Svelte component, you use the <script context="module"> tag. Anything declared inside this tag is scoped to the module, not to individual instances of the component. This is particularly useful for situations where you want to maintain a shared state or perform actions that only need to happen once, regardless of how many times a component is instantiated.
Here’s a simple example:
Counter.svelte:
<script context="module"> // This count is shared across all instances of Counter.svelte let count = 0; export function increment() { count += 1; console.log(count); }</script><script> // This script block is for instance-specific logic and state import { onMount } from 'svelte'; onMount(() => { // Call the shared increment function when the component mounts increment(); });</script><p>This component has been instantiated.</p>
In this example, the increment function and the count variable are defined in a module script and shared across all instances of Counter.svelte. Every time a new instance is created, it logs the incremented count, demonstrating that count is shared and persists across instances.
Use Cases for Module Scripts
Defining shared utility functions: For components that require common functionality, you can define utility functions in a module script to avoid duplicating code.
Creating singleton stores: If you need a store that’s shared across all instances of a component, defining it in a module script ensures that you have a single, shared store.
Optimizing performance: Since code in a module script is executed only once, it’s an excellent place for performing expensive operations like setting up subscriptions or fetching data that should be done once per component type, rather than once per instance.
Advanced Component Composition
Module scripts complement Svelte’s component composition model by allowing you to abstract and share logic effectively. For instance, you can combine module scripts with slots, props, and context to create highly reusable and customizable components.
Imagine a scenario where you’re building a library of UI components. Using module scripts, you can provide a consistent API for configuring these components globally (like themes or internationalization settings) while using instance scripts for configuration that is specific to a component’s use case.
Considerations
Scoping: Remember that variables and functions declared in module scripts are not directly accessible in the instance script or the component’s markup. To use them in the component, they need to be exported from the module script and then imported or used in the instance script.
Singleton behavior: Since the module scope is shared across instances, be mindful of side effects that might occur when modifying shared state. This is similar to how static variables would behave in class-based languages.
Stores for State Management
Svelte Stores takes a reactive approach to state management, which is different than Redux. At the core of it, see the following.
Creating a Store: The simplest form of a store in Svelte is a writable store. For example, creating a store to hold a number could look like this:
import { writable } from "svelte/store";const count = writable(0);
Subscribing to a Store: To access the value of a store outside of a Svelte component, you subscribe to it. This might be where syntax can get tricky. Use the $: syntax intuitive for reactive statements. Alternatively, you can directly subscribe using .subscribe method.
Updating Store Values: Svelte provides a few patterns for updating the store’s value, such as set, update, and using the auto-subscription feature within components with the $ prefix.
Reactivity: One of the powerful features of Svelte is its built-in reactivity. Reactive variables automatically propagate through your application.
Derived Stores
Derived stores let you create a store based on other store(s), automatically updating when the underlying stores change. This is useful for calculating derived values or aggregating data from multiple sources.
Example:
Suppose you have a store for a list of items and another derived store that calculates the total number of items.
For applications with complex state, consider structuring your store as a JavaScript object or even using a custom store. Custom stores can encapsulate more complex behavior, such as asynchronous operations or integration with external data sources.
Creating a Custom Store:
function createCustomStore() { const { subscribe, set, update } = writable(initialValue); return { subscribe, // Custom methods to interact with the store increment: () => update((n) => n + 1), decrement: () => update((n) => n - 1), reset: () => set(initialValue), // More complex operations... };}
Slots and advanced state management techniques in Svelte offer a combination of simplicity and power, enabling you to build complex and dynamic applications with less code and more declarative, readable structures.
Actions
Svelte actions are a powerful and somewhat under-appreciated feature that provide a neat way to interact with DOM elements directly. Actions allow you to attach reusable behavior to DOM elements, which can be especially useful for integrating third-party libraries or creating custom directives that enhance your application’s functionality without cluttering your components with imperative code.
An action is simply a function that is called when a DOM element is created, and it returns an object that can contain lifecycle methods like update and destroy. Here’s a basic outline of how actions work:
Creating an Action: To create an action, you define a function that takes at least one argument, the element it’s attached to. This function can return an object with optional update and destroy methods. The update method is called whenever the parameters of the action change, and destroy is called when the element is removed from the DOM.
Using an Action: You apply an action to a DOM element in your Svelte component using the use directive.
Here’s a simple example to illustrate:
Defining a Simple Action
Let’s say you want to create an action that automatically focuses an input element when the component mounts:
// focus.jsexport function autofocus(node) { // Directly focus the DOM node node.focus(); // No need for update or destroy in this case, but they could be added if necessary}
Applying the Action in a Component
You can then use this action in any component like so:
<script> import { autofocus } from './focus.js';</script><input use:autofocus />
This example is quite basic, but actions can be much more complex and powerful. For instance, you could create an action to:
Implement drag-and-drop functionality by attaching mouse event listeners to the element.
Integrate with third-party libraries, such as initializing a date picker on an input element.
Add custom animations or transitions that are not easily achieved through Svelte’s native capabilities.
Svelte makes adding animations and transitions to your web applications straightforward and intuitive, enhancing user experience with visual feedback and smooth transitions. Let’s explore how to add a simple fade transition to elements in a Svelte application, and then we’ll look at a more interactive example.
Transitions and Animations
Svelte’s transition functions, such as fade, are part of the svelte/transition module. To use a fade transition on an element, first import fade from this module.
Example:
<script> import { fade } from 'svelte/transition'; let isVisible = true;</script><button on:click={() => (isVisible = !isVisible)}> Toggle</button>{#if isVisible} <div transition:fade={{ duration: 300 }}> Fade me in and out </div>{/if}
In this example, clicking the “Toggle” button shows or hides the div element with a fade effect over 300 milliseconds.
Fade me in and out
Interactive Animation Example
For a more interactive example, let’s create a list where items can be added and removed, each with an animation. We’ll use the slide transition to make items slide in and out.
First, add slide to your imports:
<script> import { slide } from 'svelte/transition'; let items = ['Item 1', 'Item 2', 'Item 3'];</script>
Now, create a function to add a new item and another to remove an item:
function addItem() { items = [...items, `Item ${items.length + 1}`];}function removeItem(index) { items = items.filter((_, i) => i !== index);}
Finally, render the list with transitions on each item:
In the #each block, we use the slide transition to animate the addition and removal of list items. The (item) key ensures that Svelte can uniquely identify each item for correct animation, especially during removals.
Item 1
Item 2
Item 3
Customizing Transitions
Svelte’s transitions can be customized extensively via parameters. For both fade and slide, you can adjust properties like duration, delay, and easing (to control the animation’s timing function). Svelte also supports custom CSS transitions and animations, giving you complete control over your animations’ look and feel.
Using the Basic Svelte Template
If you’re looking for something simpler or specifically want to work with just the Svelte library without the additional features offered by SvelteKit, you can start with the basic Svelte template.
Review “Anytime” (especially “Obligation” tag, or open loops)
📆 Calendar
Review week’s events invites (Work)
Review week’s events invites (Home)
Review any birthdays. Make sure we add them as recurring items on Things
Physical Journal Planner
📓 Notes
Clear the inbox
Filesystem - Downloads Folder
Filesystem - Inbox Folder
Physical Mailbox
Any outstanding Drafts
How did I come about this process?
Tiago’s pillars of productivity can be broken into four categories: tasks, calendar, notes, and reading later. Of course, there’s the inevitable email inbox as well, which I’ve also included. And there’s this, the weekly review.
Prior to taking the course, half of my weekly review was tidying up, and the other half was reflection. One of the major changes that has helped me make the weekly review more accessible for me is to split those two things apart. My weekly note that I write on the website is part of my weekly reflection, and the tidying is the weekly review.
Pillars of Productivity give a ton of tactics to help tidy up for work week ahead. What I found enlightening was only to take the few things, at most two, that you can start this week. As it becomes intuitive, then continue refining the process. “Plan, Do, Check, Act”, as they say.
Annotation: Emails
📧 Emails: Work Email
I’ve made it a point to try to reduce the email load to very little. As a developer, most of my conversations are around Slack. Emails are for external chatter or sharing documents amongst a larger group. And even then, if it’s not a Google Doc or a Confluence Wiki, then I usually start one so that we can end the email chain. I know not everyone at my company likes this as there are non-technical people who are used to email transaction. It’s slowly changing, but it’s a process.
📧 Emails: Personal Email
I’ve made a point to unsubscribe to newsletters, promotions / advertising, and any other recurring email. I don’t care about weekly usage reports, social media updates, and any other periodic updates. When there’s follow-up actions involved with email, I go ahead and forward it to Things, which I’ll cover in the next section. Also, I only check my personal email at a dedicated time in the morning. Otherwise, I’ve found myself hitting refresh way too often.
When I have to reply to someone, and I have to put more thought into it, it also goes in Things.
The reason I’ve come to this conclusion is I used to use Superhuman. It was way too expensive for what it was worth for my workflow. What I took away was the following.
Use shortcuts
Get to archiving an email quickly
Unsubscribe from anything unnecessary
YMMV for the definition of “unnecessary”. I’ve found that I’ve been able to reduce my email load to a very manageable level.
Annotation: Tasks
✅ Tasks: Clear Inbox
My task manager of choice is Things. I love that it’s a one-time fee. I love that I have a special shortcut to create a new Todo. And I like how they integrated Areas and Projects to it. While I’m not strict to PARA (I have a modified system), the mental model makes sense. Especially for my work area that has many projects.
Also, I waver between my inbox and anytime. The inbox is a holding area for me to add a todo to a project and attach a date to it. If unattached, it could wind up in my “Anytime” box, which would get lost to the void. Having a weekly check-in for this helps immensely as I figure out what I have to do for the week.
📣 Shoutout to Ayush who introduced me to Things. Who also introduced me to Todoist, although I found Todoist much harder to not be overwhelmed by.
✅ Tasks: Review “Anytime” (especially “Obligation” tag, or open loops)
Cal Newport talked about an obligation list on his podcast, and it stuck with me. Tiago’s phrasing for this is an open loop. There’s no next action you can take as you’ve “delagated” this to someone else, but there might be some follow-up later (see David Allen’s GTD about how he delagates).
This could also be you promised to do something for someone else, but that time has not come yet. Like tell someone you can make it for their New Years bash in August. I’ll typically plan to put something, but not sure what that task will be just yet. There’s usually an element of time and duty. For a rule of thumb, I don’t rely on others to remember for me, so I put this in Things in a personal project that has no “when”.
Annotation: Calendar
📆 Calendar Review week’s events invites (Work)
I use Google Calendar as the default base calendar. I use Fantastical to create events easily, and Notion Calendar to indicate the time between meetings, and to pick up the zoom meeting link invites. Honestly, after Cron rebranded, I might drop it.
At the beginning of the day, I see if there are new meetings, or changed meetings, that I have to update my RSVP. During the weekly review, I use the existing meetings to plan when I’ll need focused time. I think a lot about Paul Graham’s Maker’s Schedule vs. Manager’s Schedule.
When you’re operating on the maker’s schedule, meetings are a disaster. A single meeting can blow a whole afternoon, by breaking it into two pieces each too small to do anything hard in. Plus you have to remember to go to the meeting.
Paul Graham
While Paul uses Office Hours to work in a manager’s schedule within a maker’s schedule, I opt for deep focus sessions that are unstructured. I have enough tasks through my task manager to indicate to me what to work on next, so I never worry about the content.
📆 Calendar Review week’s events invites (Home)
Whenever I plan a date weekend, or have obligations for others, I’ll schedule it in. I stopped putting recurring tasks on my calendar and shoved them over to my task manager.
📆 Calendar Review any birthdays. Make sure we add them as recurring items on Things
This one is simple. I exported all of the birthday dates from Facebook or other social media of choice and give them a text or a phone call. It’s something to remind them that I’m thinking of them and an easy lift to do.
Also, I’d rather have this in Things, so I’m doing a slow migration.
📆 Calendar Physical Journal Planner
I’ll have both calendars open and pen them in my physical planner. I use the physical planner as a working area to help me slot other things in. Paper and pen helps a lot better for me to think about the week ahead. See The Extended Mind.
Annotation: Notes
📓 Notes: Clear the inbox
I’m a prolific Obsidian user as my primary personal knowledge management (PKM). My default note folder is ”+”, previously called my inbox. Each note belongs somewhere, and maybe I’ll talk about my PKM more publicly. First, I have to hide all the private notes.
📓 Notes: Filesystem - Downloads Folder
My laptop’s downloads folder is the clutter area where anything can go in. Either they belong in by inbox, they get organized, or they go in the trash.
📓 Notes: Filesystem - Inbox Folder
The inbox folder is something worth saving and ready to file. I use my modified version of PARA to organize where things go.
📓 Notes: Physical Mailbox
Snail mail! This is a two-fold action. I rarely check my mailbox, so I go to the mailroom. Then I review quickly anything that has a follow-up action, otherwise it goes in the recycle bin.
📓 Notes: Any outstanding Drafts
I use Drafts on my phone and laptop to write down anything. Calculations, initial ideas, a working draft of a next blog post. Really, this is my scratchpad, and I’ll file them away or archive them. The syncing is the reason I keep coming back.
After Thoughts
I try to minimize this time as much as possible. Tidying up isn’t the work, so I do this to prep for my focus productive time.
I’m planning on making a short post updating what my weekly reviews are looking like, updated for 2024.
Every year or so, I’ll review my existing template and see what should be modified. It takes me a few times to get used to the format, many more months of thinking about what’s working and what’s not, and making slow incremental improvements. Look out for that soon.
Also, as mentioned last week, I spent some time updating my newsletter service. I migrated from TinyLetter to Buttondown, which you can read here.
It touts itself as a Search engine alternative w/ AI
Initial Impression: It’s got promise, but isn’t very fast.
After a week: I don’t think it replaces Google. It’s great as an alternative. Some things I’d rather still Google, and I’ll probably write-up something about it
A group of Israeli scientists wants to send a giant sail into space to block a portion of solar radiation. The shade in this artist’s rendering is enhanced to illustrate the concept.
As some of you may know, Tinyletter is out of operation. I’ve been using them since I started my blog back in November, 2014. My readership numbers have been low enough where it didn’t make sense to ever migrate off of it. The free tier limit was 500 emails.
With Tinyletter’s end meant I was in search of another service that has a free tier, or something with a reasonable price. I don’t like the idea of making people pay to read what I want to say, so I’ve chosen buttondown. Their free-tier is limited to 100 subscribers, so I’ve had to knock down the readership a bit. Also, I want to scale this back until my newsletter is back in an appropriate cadence. I’ve been thinking of keeping a monthly rhythm as my writing output isn’t as prolific as it used to. I’ll start with that for now and see if I can handle more than that.
With that, I’m going to send my first newsletter sometime in February, so make sure you are subscribed. Check out the form to on the newsletter page, or try below.
The YouTube algorithm said, it’s time to get into Chess, so that’s what I dived into this week. I was introduced to Anna Cramling, whose YouTube videos were really interesting to think about the moves as they were happening real-time.
I remember one of times I visited New York and seeing the Chess Hustlers in action. There’s something fascinating about trash talking while playing a game of chess, like in many other games like Poker or Hockey. There’s also this intellectual pursuit of watching openings, mid-game, and end-game material that’s just a wealth of knowledge, vs. studying tactics, which as a teenager appealed to me.
Anyway, I want to start playing again. What’s your favorite way to play chess, online or offline?
I created a gist
for it. The original script did not have much error handling. Something to expand
on in the future is to have that error handling within Obsidian, which I would
like to see.
Also, I used the suggester API
to give the user options on which returned item they care about using the Google
Books API.
And here’s my personal template using Obsidian properties.
I’m proud of the re-write I’ve made towards curations. The idea behind this was to combine the things that I’ve liked, consumed, gestated on, and share with you my thoughts about different things that matter to me.
For my books, I wanted the feeling you get at the bookstore where I write a short blurb about why you should pick up this book. I would spend the first few minutes reading the index cards nicely decorated about why the staff member chose a specific book. There was more potential for a chance encounter. When I read listicles online, there’s often a sense of sameness. It’s not as fun when websites all feel the same.
The same about films in a video store. I love the feeling you get, back when video stores were more popular, about staffpicks. Some small streaming services have this feeling, like FilmStruck, and more recently the Criterion Channel. When the Netflix algorithm is feeding you, or for that matter any algorithm, that hand-feel of someone’s journey into film has turned into “this is what thousands of people in your target demographic cohort also like”. And there’s something missing from that. I want to share what I like about a film, or dislike. And I also want to share why other people appear to have similar or dissonant feelings about it.
People shouldn’t feel boxed into groups of “books I like”, “movies I like”, and “music I like”. It makes everything feel dull, like these are the only categories that define our dating profile. And while I’m starting off with the books and music, I can think of other things I want to curate in the future. One thing people might not know about me is I own a 20+ year old business card collection. It reminds me of places I’ve traveled or people I’ve met. I also want to share a inspirational persons curation of people who I love and have made an impact.
Aside from everything else, I want my personal MySpace back. Back in the day, you would have a customized profile page where you make it play your favorite music, share your favorite lousy quotes, and give it your own personal flair. Even if that flair was like design vomit. It was your vomit. So with that, I’m having a little fun giving you multiple perspectives on what is essentially a listicle. But it’s my listicle. And I can call it something other than a listicle. Like an curated art exhibit. That sounds so much more sophisticated. You’re welcome.
If you missed the link above, check out curations!