.env validation with zod

Summary: You can use zod library to validate a .env file before building a project. Zod’s capabilities allow to handle very complex cases, though they are very rare.

Have you ever been in a situation when you built your frontend project and found that some value in your .env file was incorrect, or even missed? I’ve been.

After the last time when this happened to me, I decided to add validation to the build step.

Add validation to a project

  1. Install zoddotenv and tsx packages as dev dependencies
    npm i -D zod dotenv tsx
    
  2. Create a validate-env.ts file in a scripts directory:
     import 'dotenv/config'
     import process from 'node:process'
     import { z } from 'zod'
    
     const envSchema = z.object({
         VITE_BASE_API: z.string().url()
     })
    
     envSchema.parse(process.env)
    
  3. Add this to a build script in the package.json:
    build: "tsx scripts/validate-env.ts && vite build"
    

In my example I used vite and validated a single variable. You can add as many rules as you need.

Testing

Delete the .env file if it exists, and run npm run build. Zod will throw an error, because the VITE_BASE_API variable is not valid:

ZodError: [
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "undefined",
    "path": [
      "VITE_BASE_API"
    ],
    "message": "Required"
  }
]

Add the VITE_BASE_API variable to your .env, but leave it empty:

VITE_BASE_API=''

Now zod throws another error, because provided value is not a valid url:

ZodError: [
  {
    "validation": "url",
    "code": "invalid_string",
    "message": "Invalid url",
    "path": [
      "VITE_BASE_API"
    ]
  }
]

Keep in mind

When you add such thing to your project, you take additional responsibility for updating validation rules.

I Hope it was useful to someone, good luck.

Links

My Workflowy review

In this post I’ll tell about my experience with Workflowy - famous outliner service, which I’ve been using for half a year at the moment of writing.

Why

I don’t suffer from information gathering much, but I have pretty minimal needs - sync bookmarks, keep some text notes and todo items. I used to keep bookmarks with Firefox sync mechanism and my text notes/todo items with the help of protectedtext (which is a great service!). But because firefox became unusable, I switched a browser from Firefox to Vivaldi on a smartphone, while on a laptop I was still using firefox. That broke my bookmarks workflow, and at that moment I had two bookmark lists, and each of them was living its own life. What about notes? - I was happy with how I dealt with them, but it changed over time because of bad usability on a smartphone. I tried a lot of note management tools (Trello, TickTick, Notion, Org mode, Simplenote, Standardnotes, Google Keep), but finally I’ve picked Workflowy. The main reason was that I thought that I would be able to adopt it for all my needs (And strictly speaking, I succeed at this). I was using it for less than a month before I bought PRO subscription. Now the story begins…

Interface (Desktop)

Workflowy has a great UI. It’s clean and consistent, what else do I need? In general, nothing. There are some issues with the mobile app - I’ll list them in the next section.

Here, it’s worth mentioning DynaList - a clone of Workflowy, which in my opinion has a terrible user interface:

Interface (Mobile)

This is a list of my issues with the mobile interface:

  • I just can’t tap on those small arrows to expand a node
  • Slow and draggy animation

Everything else is very nice.

Keyboard shortcuts

I had been using only mouse for the first few months, but when I tried to use a keyboard, I was thrilled. Now, on desktop/web platform, about half of my actions are done with a keyboard. You can always toggle the help panel with shortcuts in three steps:

  1. Click options button
  2. Pick “Settings”
  3. Toggle the “help me learn the keyboard shortcuts”

My day to day shortcuts are:

  • Ctrl - arrow up/arrow down - Expand/collapse a node
  • Alt - arrow left/arrow right - Zoom out/zoom in
  • Ctrl - Alt - m - Move a node
  • Ctrl - Enter - Mark a node as completed
  • Ctrl - Shift - Backspace - delete a node
  • Shift - Enter - Add a new node

Slow startup

On a smartphone, the application starts very slow. I hate it when I take the smartphone to write out a quick note and have to wait more than 5 seconds for application to be loaded. Any default note taking application starts in a moment on any android device, and such slow Workflowy’s start speed is very irritating. I’m not the only one who have faced with this - there’s a ticket with this problem. The support says that 10-15 seconds for startup is “expecting” and “pretty standard for now”.

In the march of 2023, Workflowy announced “Significant speed improvements” of load time - now it’s 40% less in average. However, I personally haven’t noticed any speed improvements - maybe this is because I have a very small amount of list items, while they seem like they have boosted load time only for accounts with a large number of nodes, I don’t know.

Complex content

Workflowy is an outliner. It’s poorly suited for rich content with images, paragraphs, tables etc. With this service, you should consider every node as one single, atomic block of the whole text. Do you want to insert an image? Create a node. Need a list? Create a node for each item. Want to split some notes into paragraphs? You know what to do. And this way of working with documents may be unacceptable for people who want to use Workflowy for writing long text and complex documents.

Kanban

They’re selling it as the feature that would incline Trello users to make a switch to Workflowy.

I think this is silly. Trello sucks, but if someone uses it, Workflowy’s unintuitive kanban implementation will just enhance his attachment to Trello.

Summary

In summary, I like Workflowy, but I’m afraid that the team will be adding more and more features to it in pursuit of new users, and as a result, Workflowy will become everything, and nothing. Will I renew my subscription? Definitely not - I don’t use it heavily enough to pay for it.

Vue js: on keeping all components in a single directory

The point of article: keep components in one single directory with a flat structure.

Almost all Vue projects have a components directory, where all application’s components are kept. There are plenty of ways how you can organize them, but I think it’s better to put all your components right into components directory and do not create any sub-directories trying to make the structure obvious and simple. It may sounds strange, but in practice exactly this way is more simple and future-proof.

A flat components structure

As was told, the flat structure implies that components’ directory have no any sub-directories, just component files. Besides the components themselves, this directory contains their tests, if any. This way of organizing components has some benefits over non-flat structure:

  • It’s easier to see the whole picture

  • Imports are shorter:

    import Avatar from "./Avatar.vue"
    

    No ugly paths, like this:

    import Avatar from "@/components/main/header/Avatar.vue"
    import TextLabel from "../../Text/TextLabel.vue"
    
  • You won’t spend your time deciding where should you put your new component. This is a really good one. If you have a card with an article author’s avatar and a header with the same avatar, where should you put the “Avatar.vue”? In a “header” subdirectory or in a “card”? Or maybe create a “shared” directory and put all repetitive components here? It’s hard to decide actually. Moreover, often, when we create a new component, we don’t know whether it will be used somewhere else or not. With the flat structure, it’s not an issue.

  • Such structure forces you to re-use your components. If you group components into different directories based on their functionality, business logic or visual hierarchy, then you wouldn’t try to check whether a similar component already exists or not, or at least if you do, it will be hard to explore it.

  • Resistance to changes. no more need to move component between directories and globally rename it because now it’s not in the TodoList but in Shared directory.

Official Vue style guides

Applying official components’ naming convention dramatically increase understanding of what’s going on with your components. Consider this list of components:

Button.vue
MainLogoutButton.vue
LogoutButton.vue
Checkbox.vue
TextInput.vue
Sidebar.vue
Header.vue
AppButton.vue
AppTextInput.vue
AppCheckbox.vue
LogoutButton.vue
TheLogoutButton.vue
TheSidebar.vue
TheHeader.vue

At first glance it looks like there’s no differences and both lists provide the same information, but these styles of naming are very different. Let’s take MainLogoutButton.vue and LogoutButton.vue from the first example. What’s the difference between them? Most probably we need to check their sources, because just their names don’t tell us anything. But in the second example, we know that the TheLogoutButton.vue is the component that is instantiated only once per page, or even the whole application, and most probably it has some specific application logic that don’t allow to re-use this component, though it’s not a requirement.

The App prefix from the second example also tells us that those components don’t use any shared application state or implement any logic (such components are often called “dumb”) - they’re used only for visual representation.

Separate directories for pages and layouts

It’s very common to use pages (views) that represent whole pages of the application, and layouts directory with components that control high-order visual hierarchy ( for example, in a Profile layout we should always see TheHeader component at the top of the page, but in the Dashboard layout it shouldn’t be presented). Some frameworks (Nuxt) or plugins for vue (unplugin-vue-routervite-plugin-pages) expect those directories, so if you use them, it’s ok to move such kind of components outside the components directory, just keep track of these directories cleanliness - they shouldn’t contain non-page or non-layout components.

Links


Sublime text basics

Tabs

  • Ctrl - n - create new tab
  • Ctrl - w - close current tab
  • Ctrl - tab - move to the next tab

Command palette

If you don’t know hotkeys for a command, or don’t know if such a command even exists, use command palette. It’s the first place where you should search for unknown commands. To open the command palette, press Ctrl - Shift - p, and then type command name. For example, you want to transform selected text to upper case. This is what you should do:

  1. Ctrl - Shift - p
  2. Type text “lower”
  3. Select “Convert case: Lower case” command ( moving arrows ), and press Enter (or click )

Sidebar

  • Ctrl - 0 - focus on sidebar
  • Ctrl-k, Ctrl-b - toggle sidebar

Layouts

Sublime Text allows you to open a few tabs side by side.

  • Alt - Shift - 1 - leave only one edit buffer
  • Alt - Shift - 2 - split window vertically ( 2 tabs )
  • Alt - Shift - 3 - split window vertically by (3 tabs)
  • Alt - Shift - 4 - split window vertically by (4 tabs)
  • Alt - Shift - 5 - “Grid layout”. Two windows in a row
  • Alt - Shift - 8 - Split horizontally, 2 tabs
  • Alt - Shift - 9 - Split horizontally, 3 tabs

You can move between layout windows with Ctrl + <number> hotkeys. Ctrl - 0 - move to the sidebar, Ctrl - 1 - move to the first tab, Ctrl - 2 - move to the second tab, and so on.

Line manipulation

  • Ctrl - Shift - arrow up/arrow down - move the current line up/down
  • Ctrl - c - copy the whole line
  • Ctrl - x - cut the whole line
  • Ctrl - Shift - arrow up/down - move the line up/down

How to install packages (plugins)

First, you need to install package control. It’s the Sublime Text package manager.

  1. Open control palette (Ctrl - Shift - p)
  2. Type “Install package control”, press enter
  3. When package control is installed, open control palette and type “Install package” - press enter.
  4. Then start typing package name, for example “Color scheme”. Sublime Text will show related packages.

Multiple cursors

Sublime Text has a great support for working with multiple cursors. To set an additional cursor, use Ctrl - click. Then, all commands ( like moving cursor, char/word deletion etc) will be applied to all cursors.

There’s also nice feature in Sublime Text - you can select next occurance of the current word. It works this way:

  1. Press Ctrl - d on current word. It will be selected.
  2. Press Ctrl - d one more time. The next occurance of this word will be selected.

This is useful when you want, for example, delete or replace some occurances of a word.

Working with code

These commands may be useful for programmers.

  • Ctrl - m - move between brackets. Works even if the cursor is placed in the middle of text between them.
  • Ctrl - Shift - m - select text between brackets
  • Ctrl - g - go to line
  • Ctrl - ; - open dialog with all words in the current document. Start typing, then select required word with Enter. Then you can move to the next occurance of the word with F3

Maybe you don't need Latex?

If you don’t write a math book, you probably don’t need Latex. Just install LibreOffice, create a document in LibreOffice Writer, then click File - Export as - Export directly as PDF.

That’s all, and you don’t need to:

  1. Install Latex
  2. Install a TON of packages/fonts/language packs for it.
  3. Read answers on latex forums/stackoverflow (stackexcahange) for hours just to be able to generate a PDF file.
  4. Learn unintuitive markup language, time for learning which will never pay off.


How to install packages on startup in Emacs

Put these lines at the beginning of your .emacs:

; list the packages you want
(setq package-list '(
	web-mode
	projectile
	))

; list the repositories containing them
(setq package-archives '(("elpa" . "http://tromey.com/elpa/")
                         ("gnu" . "http://elpa.gnu.org/packages/")
                         ("marmalade" . "http://marmalade-repo.org/packages/")))

; activate all the packages (in particular autoloads)
(package-initialize)

; fetch the list of packages available
(unless package-archive-contents
  (package-refresh-contents))

; install the missing packages
(dolist (package package-list)
  (unless (package-installed-p package)
    (package-install package)))

This solution I’ve grabbed here

Atom text editor's sunset

"A hackable editor for the 21st Century”, they said.

How it was at the beginning

In 2014-2015 ( I’ve found snapshots of atom.io website for 2014 year on waybackmachine, but Wikipedia says that it was released in 2015), Github released Atom ( I personally can’t recall when I first heard of Atom) - “A hackable editor for the 21st Century”. It quickly became very popular, because… I don’t know why, I never liked it. Anyway, it’s the fact. Atom was a loud name. None of “Best editors for…” types of articles and blog posts hadn’t mentioned Atom as a honorable member of their lists. It was built using web technologies ( that wasn’t so popular as now ), it was free, and a language for its extension was Javascript - one of the most popular languages. Because of electron, Atom was RAM expensive for a text editor ( especially in comparison to Sublime Text, Emacs, Vim or Notepad++ ), but for most users it wasn’t an issue, because Atom was in trend and beside that it had some really nice features - for free and out of the box.

Microsoft bought Github

In 2018, Microsoft acquired Github. It was obvious that Microsoft won’t support Atom because it had its own product - VSCode, which is a mainstream editor/IDE now. I think that VSCode has drained a lot of ideas and features from Atom:

  • Technology (Electron)
  • Extension language
  • Built-in interface for working with git repositories
  • Collaborative editing (In Atom , it was called “Teletype”, in VSCode, it’s the “Live Share” feature)

Over the years, VSCode was actively evolving ( not always in a good direction ) and became more and more popular across developers. Let’s see at stackoverflow developer survey results.

  • 2022 - 1st place (74.48%); Atom - 12 place (9.35%)
  • 2021 - 1st place (71.06%); Atom - 10 place (12.94%)
  • 2020 - I have not found info about tools for this survey
  • 2019 - 1st place (50.7%); Atom - 10 place (13.3%)
  • 2018 - 1st place (34.9%); Atom - 9 place (18.0%)
  • 2017 - 5 place (24%); Atom - 7 place (20%)
  • 2016 - 13 place (7.2%); Atom - 9 place (12.5%)
  • 2016 - Not presented; Atom - 5 place (2.8%)

In 2019, the next year after acquiring Github, VSCode made a huge jump - from 34 to 50%.

By the way, Wunderlist service ( a todo app) was shut down the same way - it was bought by Microsoft and later closed in favor of Microsoft todo.

Sunset

In the summer of 2022, Github published a blog post, where they announced that they’re sunsetting Atom.

Atom editor sunset

Pulsar

Community has forked Atom and reincarnated it as Pulsar editor.

Official website

It’s mostly an Atom editor (that’s good), just with a new name. According to the Goals page, Pulsar’s main goal is to keep Atom and its huge package base alive and up to date. It’s a great idea.

Sublime text plugins that work

Essentially my Sublime text setup requires only three things:

  • Terminus - terminal emulator right in the editor. The nice thing is that you can open terminal in a special panel, or you can open a terminal in a new tab.
  • Sublime LSP - LSP support
  • WordingStatus - Shows words count and statistics for a document.


Far manager

Far manager is a terminal-based file manager for Windows.

Far manager screen

Links

Basic commands

  • Tab - jump between left and right panels
  • F5 - Copy file under cursor/selection to the opposite panel
  • F6 - Move file under cursor/selection to the opposite panel
  • Shift-F5 - Create copy of a file file in the same panel
  • Shift-F6 - Rename current file
  • Enter - open file
  • Shift+arrows up/down - select files
  • F3 - View file under cursor
  • F4 - Edit file under cursor

Good parts

  • Good out of the box support for a large variety of archives
  • Free

Bad parts

  • Works only on Windows, because uses Win API
  • Current Major version of Far Manager is 3. Version 2 was far more lightweight
  • Now it hasn’t an option for turning on “Black and white” colorscheme.
  • Ugly default “Blue” color that makes you sick

More articles

Execute commands in nano

In nano, it’s trivial to execute command and paste command’s output to the current buffer. That’s what Ctrl-t does.

So, for example, you want to insert list of files with specified name. you can do this in a such way:

  • Ctrl-t
  • type ls -l | grep emacs, press Enter

How to filter rows in nano editor

We can pass text in the current buffer as input to a pipe that will pass it to another program. To do this, press Alt-\ before typing command to execute.

For example, it’s very handy to filter rows. Imagine you have these rows in your buffer:

emacs
some string
I love emacs
I hate vim
I use web-mode for emacs to write html

To leave only strings that contain word “emacs”:

  • Alt-t
  • Alt-\
  • type grep emacs
  • Enter

After that buffer will conain filtered rows:

emacs
I love emacs
I use web-mode for emacs to write html