I’m building a secure ordering portal for ESC to replace a manual, email-and-spreadsheet-based workflow for training materials. The portal is built with a modern web stack.

The goal is to deliver a role-based ordering experience, automate shipping cost calculations, and lay the groundwork for a reliable “Submit order” pipeline that can integrate with their back-office systems, which include NetSuite for accounting and PBS for fulfillment.

Tech stack (current)

  • Frontend: Next.js (React)
  • Backend/Data: Supabase (Postgres + Auth, RLS)
  • Payments: Stripe (customer + saved payment methods)
  • Planned integrations: NetSuite (accounting), PBS (fulfillment)

The problem

The existing process for ordering materials relies on a form submission, ticket creation, manual follow-ups, and manual entry into back-office systems. It works, but it’s slow, error-prone, and hard to scale.

ESC needed a workflow that:

  • consolidates ordering into a single portal
  • ensures only approved users can access and place orders
  • supports role-specific permissions and invite-only onboarding
  • calculates shipping consistently (with an open question around tax requirements)
  • saves user billing and shipping details to speed up repeat orders
  • provides order history visibility inside the portal

What I built (so far)

The portal currently supports:

  • Signup and login
  • Role-based access
    • student, instructor, atp, staff, admin
  • Invite-only signup
    • staff/admin can invite users
    • only invited users can register
  • Invite permissions
    • staff can invite students/instructors/atps
    • only admin can invite staff or other admins
  • User profile editing
  • Cart and checkout
  • Shipping cost calculation
    • current open question: do we need to include tax?
  • Saved shipping addresses
  • Saved payment methods (Stripe)

Why these features matter

This foundation solves the biggest problems with the legacy workflow:

  • Security and control: Invite-only access ensures the portal stays restricted to approved users.
  • Operational clarity: Roles and permissions reduce mistakes and keep administrative actions limited to staff/admin.
  • Faster ordering: Saved shipping addresses and payment methods reduce repeated data entry.
  • Consistency: A single shipping calculation algorithm eliminates “guesswork” and spreadsheet drift.
  • Scalability: The portal architecture is positioned to automate the back-office steps that were previously manual.

The next milestone: “Submit order”

The current focus is defining what should happen when a user clicks Submit order at checkout.

The portal already has the information needed to finalize an order (items, quantities, shipping method, and address) and can capture payment via Stripe. The remaining work is to design a reliable submission workflow that can:

  • charge the user at the right moment
  • create an internal order record for the portal’s Order history
  • integrate with NetSuite for accounting records (sandbox + production environments)
  • support fulfillment system handoff (PBS)
  • handle retries safely without duplicate charges or duplicate accounting entries


This step is the bridge between a working front-end experience and a fully automated operations pipeline.

Key design considerations

A few questions drive the final architecture:

  • Tax: Is tax required on shipping in any scenarios?
  • Billing entity: Should NetSuite records attach to an ATP customer, an individual instructor customer, or be selectable based on who’s ordering?
  • Environments: Staging vs production needs stable URLs and environment-specific credentials.
  • Reliability: Submission must be idempotent (safe to retry) and traceable across systems.

Outcome (current state)

The portal is operational as a secure ordering experience with saved billing/shipping data and shipping calculations in place. The next phase is finalizing and implementing the Submit Order workflow and external integrations to fully replace the manual process.

Lessons and decisions (in progress)

Because the portal touches payments, accounting, and fulfillment, the most important work isn’t just implementation — it’s getting the workflow decisions right up front. Before building the Submit Order pipeline, I’m confirming:

  • whether shipping requires tax in any scenarios
  • which NetSuite customer record should be used for billing (ATP vs individual vs selectable)
  • the exact NetSuite transaction pattern (invoice-only vs sales order → invoice)
  • the gating rules for warnings/blocks based on overdue balances


As the project moves into integration work, I’m documenting workflow assumptions early (especially billing policy and tax requirements) so the submission pipeline can be designed correctly the first time, with fewer downstream changes.

Next steps

  • Finalize the Submit Order workflow and idempotency requirements
  • Connect to NetSuite sandbox and confirm the required transaction type and fields
  • Integrate PBS order creation and store references back in the portal
  • Populate Order history with real order records and statuses


This project has been a good reminder that building “the portal” is the easy part — the real work is translating a messy real-world workflow into something deterministic, secure, and auditable. I’ve had to get comfortable sitting in ambiguity, asking better questions, and documenting assumptions before touching the Submit order button. It’s been frustrating at times because every unclear policy decision (tax, bill-to behavior, overdue rules) ripples into architecture and data design, but working through that has made me sharper. I’m leaving this phase with a much stronger understanding of how payments, accounting systems, and fulfillment fit together — and a healthier respect for the unglamorous details that make software actually work.