Andre Ortiz
Product Design, Strategy & Systems.
Front-end Development & Prototyping

Front-end Development & Prototyping

Learn how I bridge the gaps between product, design, and engineering teams.

Should designers learn to code?

Yes! Thanks for reading.

const skills = [
  "storytelling",
  "design",
  "illustration",
  "motion graphics",
  "code",
];

if (skills.includes("code")) {
  // Todo: Create Function
  console.log("Let's go!");
}

But seriously, being able to work across the disciplines and contribute to the products we design is incredibly rewarding. Don’t missunderstand, I’m not a “full stack” guy but I know enough about the development, front and back, to be supportive in most engineering conversations - and isn’t that what it’s all about? Supporting our teams.

As the industry has evolved, so have I. I have learned a lot of languages, frameworks, and build systems. Here are a few: HTML, CSS, Javascript, Ruby, Python, PHP, C#, ClojureScript, Webpack, Vite, React, Vue, Angular, Style Dictionary, Tailwind,, and so many others.

Developing Imagination

Today, I find myself using React, Vite, and Tailwind when I want to quickly prototype something. This combo is a great way to showcase simple ideas, communicate interactions, and create an artifact that could eventually become production code. I dive a bit deeper on this topic here.

Checkout my current starter project, react-vite-template, if you’re interested.

A Quick Overview

react-vite-starter

This project needed to support a number of qualities:

  • React/Typescript was a the language of choice
  • Customizations had to be simple
  • Prototyping had to be fast
  • It needed to be deployable, destroyable, and password protected

What’s in it?

I used a custom component called AuthenticationWrapper to check for a session when certain pages were requested.

const AuthenticationWrapper = (props: any) => {
  const [isAuthenticated, setIsAuthenticated] = React.useState(false);
  const [inputPassword, setInputPassword] = React.useState("");

  useEffect(() => {
    const storedAuth = sessionStorage.getItem(SESSION_KEY);
    if (storedAuth === password) {
      setIsAuthenticated(true);
    }
  }, []);

  const handleSubmit = (e: any) => {
    // handle login
  };

  // Continue if authenticated or login
  if (isAuthenticated) {
    return <AppProvider>{props.children}</AppProvider>;
  } else {
    return (
      <Login
        loginCallback={handleSubmit}
        setInputPassword={setInputPassword}
        inputPassword={inputPassword}
      />
    );
  }
};

Additionally, I used the React useContext hook to share global state across my routes.

// AppContext.tsx
export const AppProvider = ({ children }: { children: React.ReactNode }) => {
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount((prevCount) => prevCount + 1);
  };

  const value = useMemo(() => ({ count, incrementCount }), [count]);

  return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
};

// App.tsx
import { useContext, useEffect } from "react";
import { AppProvider, AppContext } from "./AppContext";

const Action = ({ count, incrementCount }: any) => {
  return (
    <div className="flex gap-4 items-center">
      <Button
        size="large"
        type="primary"
        onClick={() => {
          incrementCount();
          console.log({ count });
        }}
      >
        Increment Count
      </Button>
      <code>{JSON.stringify({ count })}</code>
    </div>
  );
};

Once I had the all necessary elements, I had to ensure that I could deploy it. Vercel has been a faily reliable platform for hosting projects like these. Again, if you’re interested in these details, check out my starter template, react-vite-template, on Github.