私は次の最初の温泉を作りました.js


背景


私は約10年の間、何らかの形でソフトウェアエンジニアでした.そして、Python、PHP、Swift、C Chiang -からバニラJS、JQuery、Vue、および反応に何かで働いています.過去数年にわたって、私は現代のJSフレームワークをよりよく知っているようになっていました.私はVueで働いている私の日の大半を過ごします、そして、私は彼らの両方のより良い理解を持つために反応で若干の側プロジェクトをつくりました.
私はこれらの技術戦争のファンでありません、そして、私にこれらのJSフレームワークは最終的に同じものです.私は少しVueでの作業を楽しんだが、それは個人的な好みのためだけです.

考え


数年前、私は整備士に車を取らなければならなかった.何も聞いていない一週間後、私は彼らを呼びました.明らかに、彼らはエンジンを交換する必要がありました(このmake/modelで既知の問題でした).この待ち時間.呼び出し.…を待つ.呼び出し.仕事が完了するまで、サイクルは数週間起こりました.嫌いだ.
したがって、私は、サービスプロバイダは、電子メール、SMS、またはプッシュ通知を介してお客様に通知することができます顧客にこれらのステータスの更新を提供するために簡単に使用できるプラットフォームを持っているサービスプロバイダに役立つ可能性があるという考えを持っていた.これは、更新履歴などのジョブのタイムラインビューを提供することができます..そして可能であれば、彼らの部分にあまりにも多くの追加の仕事を作成しないように既存のツールに統合することは素晴らしいでしょう.しかし、それは同じ質問をして繰り返し顧客の呼び出しから同じことができました
しかし、私はそれについて何もしませんでした.長い話短い、私は最終的に物事を構築するために周りに約4年かかりました.
エンターStatus Tracker . これを書く時に、それはまだ初期の初期のアクセスです.これらの初期のアクセスを得ることに興味のある着陸ページにサインアップフォームがあります.

次はなぜ。js


私がバックグラウンドで言及したように、私は通常Vueを好む.私はNuxtでそれを構築するつもりでした.私はあまりそれを使用していないので、私は素晴らしいことを聞いたことがあります.
そしてリリースBedrock . それは本当にすべてのボックスからすでにセットアップをした
  • TypeScript
  • GraphQL

  • GraphQL Codegen and Nexus DBモデルからクライアントクエリとコンポーネントへの完全なスタック入力を意味します.

  • Passport - ユーザーauthはすでにセットアップと行く準備ができて

  • Stripe - サブスクリプション計画の基本的なストライプの統合は、構成と作業.
  • 好きなものPrettier and ESLint 既にコーディングし、事前にコミット中に問題を修正し、自動修正の問題を構成します.

  • Postmark トランザクションメール用
  • 他にいくつか.
  • 全体的に、私はまさにSaaSを構築するために私が初めて必要としていました.それは私が私がそれを得たとすぐに私のカスタム機能を追加を開始する準備ができました.マックスは、我々がお互いを支えて、我々のプロジェクトを共有することができるように、岩盤の許可を購入した人々のために不協和サーバーをつくったと言いさえしません.
    それがリリースされる前に、私はあらかじめそれを命じて、大いにそれを得ました.しかし、完全な価格でさえ、それは価値がある以上です.
    それで、このセットアップは、Vueから反応するスイッチの価値がありました.それは私にも反応についてもっと学ぶ機会を与えた.

    テクニカルゲット


    私は、詳細にここに詳細に行かないようにしようとします、しかし、あなたが特に何かについてもっと知りたいと思うならば、私に知らせてください、そして、私はそれについてより小さなポストを書くことができます!私はまた、私が作成したモデルとビューのすべてについてドローンになるつもりはありません.私はちょうど私が働いてもっと楽しく、面白い、または困難ないくつかをカバーしたい.
    ここで我々は何をするつもりです:
  • Hosting
  • Frontend component library
  • Email notifications
  • SMS notifications
  • URL Shortener
  • Scheduled jobs
  • Customer portal with custom branding
  • ホスティング

    I decided to try Vercel for hosting this project. I have used Netlify in the past, but since Vercel was built by the same people who built Next.js, and it was originally created for Next.js, I thought it would be a great fit. It was simple to setup and works pretty well. A few caveats I had to work around with my specific setup, but they typically had documentation around this.

    For hosting the database (which is Postgres) I went with supabase . 私は既に使用していたPrisma ORMのためにそれは基盤で来たので、私はsupabaseからSDJを使用しませんでした.しかし、新しいアカウントを設定し、接続文字列を取得し、既存のコードにフックするのは簡単でした.彼らはこのようなプロジェクトのための良いフリー層を持っている.そして、私は彼らのUIを楽しむときにWebアプリケーションを使用します.

    フロントエンドコンポーネントライブラリ

    I decided to go with Material-UI 多くの理由で.
    初心者にとっては、デザインがとても得意ではないので、より良いデザインに私を案内する独創的なフロントエンドフレームワークが欲しかった.非常に多くのカスタマイズを必要としなかった何かは、それがまともに見えるようにしました.私は物質のUIについての大きなことを聞いたことがあり、それは偉大な次の作品.jsまた、私の非創造的な脳を刺激するいくつかの良いデモを提供します.
    私は基本的なカラーパレットを決定し、テーマの設定を使用してカスタムテーマを作成しました.その後、ほとんどのインポートと使用され、いくつかの調整の間隔とそのような.それは美しいではないが、私の目標は使いやすく理解することだった.後で変身について心配します.

    電子メール通知

    For sending transactional emails I stuck with Postmark JS as the boilerplate came with it baked in. I could have switched it out fairly easily, but decided to stick with what was ready for me.

    I setup some templates in Postmark using their pre-made templates as a starting point. I could define variables in their template (like a user's name or a company/project name). Then using their SDK it was pretty simple to send emails with the intended template and variables. Here's an abbreviated example.

    import { Client } from "postmark";
    const client = new Client(API_TOKEN);
    
    client.sendEmailWithTemplate({
      From: FROM_EMAIL,
      To: input.to,
      TemplateAlias: input.template,
      TemplateModel: {
        name: input.name,
        company_name: input.company,
        action_url: input.url,
      },
    });
    

    Postmark was pretty easy to setup and use, and their default templates are better than what I would have created. So far I am pretty happy with them.

    SMS通知

    Originally I did not plan to have SMS notifications. However, I had some conversations with potential customers, and it was brought to my attention that the intended users might be on their phones in the field. For example, a construction crew on the project site. I decided to go ahead and add this, even though it sort of stretched the MVP concept.

    For the frontend component, I decided to use Material-UI Phone Number , どちらがフォークですかreact-phone-input-2 材料UIのために作ら.私は自分の電話番号の入力を構築する時間を過ごしたくなかったが、自動形式と国の選択を持って良い機能だった.
    私も使用することを決めたgoogle-libphonenumber サーバー側の書式設定と電話入力の検証を処理します.
    SMSの通知を送信するにはAmazon SNS . 私はAWSに関連した何かで働いているたびに私はすべてが正しく構成される方法を把握しようとして時間を無駄にしているので、これを行うことを躊躇していた.幸いにもSNSはあまり複雑ではなく、彼らのドキュメントは私を助けてくれました.つの大きな利点は、AWSの無料層で無料100万リクエストのようなものを得ることです.これは、私を始めるために十分でなければなりません.
    私がSNSを使用している方法の切られたバージョンは、ここにあります.
    import {
      SNSClient,
      PublishCommand,
      PublishCommandInput,
    } from "@aws-sdk/client-sns";
    import { PhoneNumberFormat, PhoneNumberUtil } from "google-libphonenumber";
    
    export interface SendSMSInput {
      to: string;
      subject: string;
      text: string;
    }
    
    const sns = new SNSClient();
    
    // Create instance of phone util for formatting
    const phoneUtil = PhoneNumberUtil.getInstance();
    
    export const sendSMS = async (input: SendSMSInput) => {
      // make sure phone is E164 format
      const phone = phoneUtil.parse(input.to);
      const params: PublishCommandInput = {
        Message: input.text,
        PhoneNumber: phoneUtil.format(phone, PhoneNumberFormat.E164),
        Subject: input.subject,
      };
      try {
        return sns.send(new PublishCommand(params));
      } catch (err) {
        console.error(err, err.stack);
        return null;
      }
    };
    

    URL短縮

    Once I setup SMS notifications I realized that I would need a URL shortener. Since I'm using the Magic Link authentication process, the URLs can be quite long. In an SMS, this is terrible to see.

    After some research, I decided to give Kutt やってみなさい.それはオープンソースであり、自由であり、それを使いやすくすることができるノードSDKがあります.
    それはセットアップと使用が簡単だった.私がそれを使う方法の短縮版は、ここにあります.
    import Kutt from "kutt";
    
    export const getShortUrl = async ({ expiresIn, target }) => {
      const kutt = new Kutt();
      kutt.setTimeout(expiresIn);
      const url = await kutt.submit({ target });
      return url.shortUrl;
    };
    

    スケジュール仕事

    Since I decided to host on Vercel, I don't really have a server to run crons on. The backend is all serverless functions. But, one feature that Status Tracker provides is the ability to set a reminder for yourself. For example, when you create a new job, you want to remind yourself 1 hour after the job is scheduled to update the status.

    In order to create these scheduled reminders, I needed to be able to have a cron or some sort of scheduled job. I thought about going with another AWS service for this, but once again I'm always hesitant about this.

    Then I found Quirrel . 彼らの全体のことは“Quirrelはケーキとしてシンプルなジョブキューになります.”これは私が探していたものです.
    医者は簡単でまっすぐに見えた.技術はオープンソースです.価格プランは、私のような小さなSaaSに適しています.私はそれに行くことに決めた.
    基本的には、新しいキューに入れられたジョブを作成するAPIエンドポイントを作成しました.このエンドポイントは、ジョブを実行するときにKirrelに通知し、API終了点をその時点で呼び出します.それから、私はスケジュールされた時間でQuirrelから呼び出しを受けるもう一つの終点を持っています、そして、それは参照されたデータを使用して通知を送ります.
    スローガンはかなりの場所だった.それはセットアップに簡単でした、医者はそれを通して私を歩きました.今までのところ、私はサービスにも満足しています.

    カスタマーポータル

    This was the fun part. I wanted to create a custom sub-domain for each organization who uses Status Tracker. I also wanted to give them the ability to use their own branding instead of ours, similar to how Stripe does with their checkout portal.

    When a user creates a new organization, they provide the name, and we auto-generate a subdomain. However they are given the choice to change the subdomain if they don't like what we created.

    一旦会社がつくられるならば、彼らが彼らの会社セッティングの下で選ぶならば、彼らは彼らのブランディングを構成することができます.

    私がこの点で理解しなければならなかった2つの主要なものがありました.
  • どのように私は自動的に私は手動でこれを毎回行う必要がないように、会社のサブドメインを作成できますか?
  • どのようにデータベースの値から来る動的なテーマを使用して顧客ポータルを構築するには?
  • サブドメインの作成


    私は、新しい会社が登録するたびに、NGNX ConfigsとSSL certsをセットアップすることに対処したくありませんでした.私は一般的な顧客ポータルを指すワイルドカードのサブドメインを使用しようとすることを決めた.
    私はVercelを使用してアプリケーションをホストしているので、私はvercleに私のドメインサーバを指し示し、使用するDNSを設定しました*.statustracker.app この二次アプリ.VercelはSSLのCERTの世話をした.
    アプリ自体(別のNext . jsクライアントのみアプリ)では、私は同じ作成theme.ts デフォルトのステータスとして標準的なステータストラッカーブランディングファイル.私は既にカスタムを持っていた_app.tsx ファイルをいくつかの他のものを扱うので、そこに私はカスタムを追加getInitialProps 関数.

    NOTE - I have discovered since building this that perhaps I should be using getServerSideProps instead. I will be testing this change soon.


    この関数では、サブドメインからスラッグを使用して会社を取得するAPIを呼び出します.見つからない場合は、メインステータストラッカーサイトにリダイレクトします.それが会社を見つけるならば、それは構成要素にテーマセッティングを返します.

    カスタムブランディング


    私はテーマプロバイダを作成するコンポーネントでは、私は任意のカスタムテーマの設定は、アプリケーションのプロップによって提供されるテーマのプロバイダを作成する前に、デフォルトのテーマを使用してフォールバックとしてチェックします.
    ログインページのブランディングの違いのサンプルです.

    それはラップだ


    それは私がアプリを構築私の経験について書くことを考えることができるすべて面白いです.進行中のプロジェクトについてもっと書きたいと思っています.あなたがフォローすることができますまたはステータストラッカーのマイルストーンに沿って従ってくださいthe Indie Hackers product page .
    あなたが質問を持っている場合、または特に何かについての詳細を知りたいコメントを残して、私に知らせてください!