Josh Pitzalis

Improving Retention

Read this first

Reaching out to people and finding work as a freelancer

I started my freelancing career as a personal trainer. The easiest way to get started as a personal trainer is to work for an agency. They take a cut of your profits, but they set you up in a gym and show you the ropes. Showing me the ropes meant a two-day workshop on how to find and work with clients. I did the workshop over a decade ago, and the one thing that stuck with me was something called the 6 by 6 promise. They promised that if I did one of six specific things for six hours a day, I would be fully booked with paid clients in 2 months. I used this approach to successfully find clients when I first started working in a gym, I used it again when I set up my own clinic years later, I used it again when I switched careers and became a freelance software engineer.

They gave us a pdf at the end of the workshop, and I’ve held onto it so I can actually show you the original diagrams to...

Continue reading →


Freelancing as a five-step process

freelancing in five steps.png

Being an independent contractor lets you make a living making the difference you want to make in the world. Nobody gets to tell you otherwise. You can decide what you do, how you do it and who you do it for.

You are still subject to the realities of the market. You can decide to make paper aeroplanes for a living but if no one pays you then you don’t have a service. Provided that there is a market for what you want to do, freelancing means being free to make your own choices about how you do it and who you do it for. Nobody can stop you.

If there is a change you want to help people make, you can think about helping them make that change as a five-step process:

  1. Creating an offer. This covers what you will do for them, how you do it and who you do it for. It should also cover what you won’t do and who you won’t do it for.
  2. Building a network. This means putting a list of potential...

Continue reading →


Week Ten

I’m building a product called Client Tree. It’s an app that helps freelancers find clients by word of mouth.

I’ve been tracking user retention to guide product development. Retention measures how many people come back and use an app after they first sign up.

Screenshot 2019-12-30 at 5.37.21 PM.png

At the moment, you can see that 20% of the people who sign up continue to use the app a week after they create an account. These people continued to use the product for about 6 weeks and then stopped using it altogether.

To try and fix this I implemented a fancy email onboarding feature and something called a hustle meter about 3 weeks ago. Both features seem to have had no impact on retention.

I am not happy with how I am measuring the impact of the features I am building. I don’t know exactly what impact the email onboarding feature and the hustle meter had.

What I would like is to be able to compare the retention scores of...

Continue reading →


Why in the world would anyone want to freelance?

This is a caption

Being an independent contractor is a shit ton of work. You have to do what you do, and then run a business at the same time.

If you thought freelancing was an easy way to start making some money on the side, you are wrong.

If all you want to do is be paid to do something you love, you are better off finding a job. You’ll get a nice, steady pay-check at the end of every month, and plenty of time to practice the skill of your craft.

Freelancing only makes sense if there is a change you want to make. As an independent contractor, you get to make a living making the difference you want to make in the world. Nobody gets to tell you otherwise. You get to decide who you work for, what you do, and how you do it. Freelancing means being free to make your own choices, choices that you are ultimately responsible for.

I’m putting together a free online course that helps you avoid a lot of...

Continue reading →


React Testing Library and Redux Observable

You can use the test scheduler to test sequences in epics but integration testing breakdown if you don’t include redux observable in your test redux wrapper.

Here is how I successfully managed to integrate redux observable with react testing library by mocking out the store. This wrapper replaces the default react-testing-library render method with a render method that gives components access to redux, react-router and redux observable in a test environment.

import React from 'react';
import { render as rtlRender } from '@testing-library/react';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import { createEpicMiddleware } from 'redux-observable';
import { rootReducer, rootEpic, dependencies } from './store';

function configureStore(initialState) {
...

Continue reading →


Redux Observable Loops

You can make redux complicated but at the most fundamental level, you have a view layer that lets you fire actions that can update the state. There is middleware and actions hit reducers which update the store, but let’s consider those implementation details. Practically speaking, it’s a tiny action loop where View > Action > State.

Redux observable introduces a separate action loop that runs alongside the tiny loop. The view layer lets you fire actions that trigger epics, which can fire off more actions, that can update the state. So it’s View > Action > Epic > Action > State.

This diagram helped me put all this all together.

PNG image-0FBFB8DA8517-1.png

A few important details:

  1. All actions will run through the tiny loop before they run through the epic loop.
  2. All Epics must return an action or it’s doom.
  3. If your epic returns the same action it received, you will create an infinite loop of doom.
  4. If your...

Continue reading →


Using Redux Observable For Async Stuff

Redux doesn’t handle async work too well. Thunk is the go-to solution, but it’s not always great for testing.

Here is how to do a basic async data fetch with redux observable;

export const exampleEpic = (action$, state$, { later }) =>
  action$.pipe(
    ofType('projects/updateTitle'),
    debounceTime(1000),
    switchMap(({ payload }) =>
      from(later(2000, payload)).pipe(
        map(res => ({
          type: 'projects/fetchFulfilled',
          payload: res,
        }))
      )
    )
  );

Thunks are called epics in redux observable. All epics take three parameters (action$, state$, { dependancies }). The last two are optional.

The action$ parameter is a stream of all redux actions emitted over time. state$ is the state of your redux store. dependencies can contain any side effects that you want to use in your epic. Passing in side effects as dependencies is super handy...

Continue reading →


Week Six

It’s been six weeks since we launched Client Tree.

Client Tree is an app that helps freelancers find clients by word of mouth. It reminds you to stay in touch with people and help them in meaningful ways.

Like any business, getting an app off the ground means keeping at least three balls in the air. You have to build the product, promote it and get feedback from the people who are using it, all at the same time. There are always too many most-important things to do.

To keep it simple, at least on the product side of things, we only track one metric.

retention8dec.png

This chart shows you the number of people who have continued to use the app after they first signed up. So 100% of the people used the app in the week they signed up. Only 25% came back to use it again after the first week.

That number has been steady for the last 5 weeks. This is a good sign. This means that a quarter of the people...

Continue reading →


Setting Up Redux Observable

If you are adding redux observable to a new redux project, the first step is to install it along with RXJS

npm i redux-observable rxjs

The next step is to set up the middleware.

Create a middleware and pass it to the createStore function from Redux. Then you create a root epic that combines all your epics and call epicMiddleware.run() with the rootEpic.

import { createStore, compose, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import { combineEpics } from 'redux-observable';
import  { epicA } from './epicA';
import  { epicB } from './epicB';

export const rootEpic = combineEpics(
  epicA,
  epicB
);

const epicMiddleware = createEpicMiddleware();

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default function configureStore() {
  const store = createStore(
    rootReducer,
    composeEnhancers(
...

Continue reading →


Creating Your Menu

If you’ve ever hired anyone, then you probably know that there’s a whole range of questions spinning around in their head: Can I trust this person? How much will this cost me? What does the process look like? What do I even need? What if the scope spirals out of control and I waste my precious budget with the wrong person?

Creating a menu of your freelancing services is a painless way of offering a fixed-price service with a pre-defined process. You let people know exactly what they’re getting and how much it will cost from the get-go.

Besides making you easy to hire, giving people clear options up front eliminates the need for proposals. When you package up your service, you’re defining what the deliverables are, what you’ll do, what the price will be, and what the scope of work will cover. There is no need for back and forth, you have already boiled everything down to a simple...

Continue reading →