Skip to content

Forma

Forma is a multipurpose admin dashboard built with React, TypeScript, Vite and Tailwind CSS. It includes 41 screens and state examples for business dashboards, SaaS analytics, CRM, invoicing, subscriptions, support and project work.

Explore Forma · Open the live demo

This guide covers Forma 0.2.0. The source package also includes setup, customization, module and integration guides in its docs/ folder.

  1. Download the Forma ZIP from your Lemon Squeezy purchase and extract it.
  2. Open a terminal in the extracted folder containing package.json.
  3. Use Node.js 22.12 or newer in the Node 22 line, with npm, and run:
Terminal window
npm ci
npm run dev

Open the address printed in your terminal, normally http://127.0.0.1:5173. Start at /dashboard for the business overview or /overview for the project workspace.

No API keys or environment file are needed to explore the included demo. The package was verified with Node 22.22.3. Its lockfile records the installed dependency versions.

Terminal window
npm run build
npm run preview

The build checks TypeScript and writes production assets to dist/. Preview serves that build, normally at http://127.0.0.1:4173. Run the app through a server rather than opening index.html directly.

The first visit loads fictional records. Changes persist in the current browser, including projects, invoices, opportunities, tickets, subscription preferences and saved reports.

Use Demo guide → Reset sample data to restore the original records. This discards local demo edits. Changed fixture files will not replace an existing browser save until you reset it or use a fresh browser profile.

ApplicationStart with
SaaS productProduct analytics, pricing, billing, authentication and onboarding
Client portal or agency toolProjects, clients, milestones, files, opportunities and invoices
Analytics dashboardTrends, acquisition, conversion funnels, retention, events and saved reports
Internal business toolBusiness overview, sales pipeline, support, calendar, team and reusable tables

The sidebar groups screens under Business, Workspace, and Manage & build. Workspace setup lets you choose Studio, SaaS or Client work and your preferred appearance. Every module remains available after setup.

The 41-screen count includes individual account flows and system-state examples. Parameterized detail routes use your record IDs.

AreaRoutesIncluded behavior
Business overview/dashboardCollected invoice revenue, open opportunity value, support counts, current plan and links to related records
Workspace overview/overviewProject totals, status and workload charts, milestone progress and interactive completion timeline
Projects/projects, /projects/:projectIdGrid/list/board views, filters, creation, editing, milestones, comments, file metadata, starring and archiving
Tasks/tasksPersonal/team views, assignment, priorities, dates and completion
Clients/clients, /clients/:clientIdContact records, notes, projects, opportunities, invoices and support conversations
Files and inbox/files, /inboxSearchable metadata library, activity, read states and contextual links
Team and preferences/team, /settingsMembers, invitation workflows, role labels, profile, workspace preferences, appearance and density
Sales pipeline/pipelineEditable opportunities, owner filters, drag-and-drop stage changes, accessible stage selects, list view and CSV
Invoices/invoices, /invoices/:invoiceIdLine items, tax and totals, status filters, bulk actions, draft/sent/paid/void states, detail, CSV and printing
Plans and billing/pricing, /billing, /billing/historyMonthly/annual plans, plan changes, cancellation/resume, usage, billing identity and sample receipts
Product analytics/analyticsDate/channel filters, interactive trends, acquisition and accessible chart data
Analytics detail/analytics/funnels, /analytics/retention, /analytics/events, /analytics/reportsConversion funnel, cohort table, event search/details, saved views and exports
Support/support, /support/:ticketIdNew tickets, status/priority/assignee, conversation threads, replies, internal notes and resolution
Calendar/calendarMonth navigation, project filter, milestone dates and links back to work
Integrations/integrationsCatalog search, categories and local connection states
Developer tools/developerShow-once demo key creation, copy, permission labels and revocation
Security/security, /security/auditVerification preferences, sample sessions, role guidance and local business activity
Account flows/auth/sign-in, /auth/sign-up, /auth/forgot-password, /auth/verify-emailValidated account forms, recovery preview and verification flow
Workspace setup/onboardingWorkspace/use case, appearance and confirmation steps
Interface patterns/patterns, /patterns/forms, /patterns/tables, /patterns/statesReusable forms, tables, selection, pagination, validation, empty/loading/error and confirmation examples
System states/status/403, /status/404, /status/maintenanceApplication-state designs with recovery links

Client relationships use IDs. A client detail page collects its projects, opportunities, invoices and support conversations. Global search finds projects, clients, milestones, business records and application pages.

Project progress comes from its milestones. Completing a project completes its unfinished milestones; reopening work updates the project state. Archived projects stay in the data but leave active collections.

The sales pipeline supports dragging cards between stages. Its stage selects provide the same action for keyboard and touch users. The project board is a separate view that groups projects by status.

Create an invoice, choose a client and add line items. Quantity, unit price and tax determine its total. Currency is stored in integer cents; each line and the tax amount are rounded before totals are displayed.

Draft invoices can be edited, marked sent and later marked paid. Collected revenue on the business dashboard derives from paid invoices. Voided invoices remain in the record. Print / save PDF opens the browser print dialog; Export line items downloads a CSV.

The pricing page demonstrates monthly and annual subscription plans. A confirmed change updates billing and usage limits. Plans with too few seats for the current team show an error. Cancellation and resume controls change the local subscription state.

The subscription prices inside the demo are fictional example plans, separate from the purchase price of the Forma template. Receipt history is sample historical data and does not change when you select another plan.

The analytics module uses a deterministic 90-day sample dataset. Period and channel filters drive the totals, trend chart and funnel. Hover or focus chart points for values, or open the chart’s data table.

Saved reports retain their period, channel and metric. They reopen a view with those filters rather than saving an immutable snapshot. The retention table demonstrates a cohort model; the event explorer uses a separate sample fixture. Connect these views to your analytics service when building your application.

The workspace completion timeline is separate: it can show current milestone completion dates or labeled sample history. Reopening a milestone clears its current completion date; this timeline is not a permanent event log.

New support tickets open their conversation immediately. Save a reply or internal note, change priority or assignee, and resolve a conversation. Messages stay in the browser until you connect a delivery service.

The account screens demonstrate sign-in, sign-up, recovery and verification. Use 123456 for the demo verification code. Passwords stay in transient component state and are never stored or sent. Onboarding saves workspace and appearance preferences, then opens the selected starting dashboard.

ChangeFile
Sidebar wordmark, navigation, search and shared shellsrc/app/App.tsx
Account-page wordmark and setup screenssrc/features/AccountFlows.tsx
Default workspace name, tagline, view, density and appearancesrc/data/entities.ts
Document title, metadata, initial appearance and favicon linkindex.html
Faviconpublic/favicon.svg
Font and stylesheet importssrc/main.tsx
Light palette, typography and base UIsrc/styles.css
Dark palette and component overridessrc/theme.css
Business modules, tables and invoice print layoutsrc/business.css
Project cover sizing and compact densitysrc/covers-density.css
Page and collection transitionssrc/motion.css, src/components/MotionGroup.tsx

Update the light and dark values for --canvas, --panel, --ink, --muted, --line, --accent and --accent-light together. Check explicit component colors, badges, chart labels and focus rings after changing the palette.

Plus Jakarta Sans is bundled locally through Fontsource. To change it, update the font import and the --font-sans token, and retain the license notices for any fonts you distribute.

Appearance supports Light, Dark and System. The early script in index.html applies the saved choice before the app renders. Keep it aligned with WorkspaceProvider.tsx if you change the persistence key or appearance behavior.

Project covers live in public/images/projects/. Each artwork key has two files, for example orbit.jpg and orbit-small.jpg. The included sizes are 1536 × 1024 and 768 × 512.

Replace both files with artwork of similar proportions. Keep text in the interface rather than baking project names into the image. Adding a new artwork key also requires updating the project schema, seed data and related selectors. The package’s docs/PROJECT-IMAGES.md records the included artwork’s provenance.

  • src/data/workspace.ts: workspace schema, project/member seed data, reducer and restoration.
  • src/data/entities.ts: clients, tasks, notifications and default preferences.
  • src/data/business.ts: opportunities, invoices, tickets, plans, subscriptions, integrations, keys, reports and audit entries.
  • src/data/analytics.ts: sample reporting records, filters, aggregations and event fixtures.

Extend schemas, types, forms and migrations together. The business subtree defaults into older workspace saves without resetting existing projects or preferences. Keep foreign-key relationships intact when changing sample records.

For an empty starting workspace, update all relevant seed arrays, including the business modules, and retain the current member and required settings. Validate the result with workspaceSchema and check both fresh-start and reset behavior.

Routes and navigation live in src/app/App.tsx; the browser router is created in src/main.tsx. Add a feature under src/features/, then connect its route, navigation entry and page title. Authentication uses a separate layout branch.

When removing a module, also update global search, dashboard links, client-detail links and onboarding destinations that point to it. Keep the shared provider as the single state source for related records.

Use src/components/BusinessUI.tsx for business panels, metrics, pills, form dialogs, simulated save handling, tables and CSV export. Shared dialogs, pending fields and empty states also live in src/components/ui.tsx.

The included data flow is:

Form → validation → simulated save → typed action
→ shared reducer → workspace state → browser persistence

src/app/WorkspaceProvider.tsx exposes state, dispatch, notifications and the simulated request lifecycle. run accepts a synchronous callback, waits 450 ms and optionally fails once through the Demo guide’s error toggle.

Replace this lifecycle with an awaited service request. Validate the server response, update shared state with canonical IDs and dates, then show success and close the form. Keep submitted drafts on failure and prevent duplicate submissions while a request is pending. Simply passing an asynchronous function into the existing run helper does not make it await that request.

CapabilityService work to connect
Accounts and rolesAuthentication provider, sessions, account recovery and server-enforced permissions
Workspace dataAuthorized reads/writes, persistence, validation and conflict handling
FilesUpload bytes, store object references and authorize previews/downloads
Invitations and supportInvitation tokens, email delivery and conversation storage
Plans and paymentsCheckout, subscription updates, payment events and canonical billing records
AnalyticsEvent collection, reporting queries, retention cohorts and aggregation rules
Integrations and keysOAuth or API connections, real credential issuance, scopes and revocation
Security and auditEnforced verification, actual session revocation and durable server audit records

Search every dispatch( call site when integrating: some immediate controls dispatch directly rather than using the form-save helper. Remove or adapt the browser persistence, demo reset, failure simulator and fictional fixtures when your server becomes authoritative.

File additions currently save metadata only. Integration toggles do not call external services. Demo keys cannot access an API and only their suffix is persisted. Role labels, verification preferences and sample sessions are interface examples; access must be enforced by your backend. The audit list retains the latest 100 local business actions.

Terminal window
npm test
npm run build
npm run test:e2e

The package includes 18 state tests and 38 Chrome browser journeys, verified from a clean 0.2.0 extraction on macOS. Browser tests use installed Google Chrome by default and isolated browser contexts.

For Playwright’s Chromium on macOS/Linux:

Terminal window
npx playwright install chromium
PLAYWRIGHT_CHANNEL=chromium npm run test:e2e

To run against an isolated development port on macOS/Linux:

Terminal window
CI=1 PLAYWRIGHT_PORT=5177 npm run test:e2e

After customization, check the affected workflows, keyboard navigation, mobile layouts, light/dark appearance, compact density and reduced motion. When adding services, also exercise request failures, session expiry and unauthorized access.

Deploy the contents of dist/ to your static host. The supplied build targets the root of an origin, such as https://app.example.com/.

Configure the host to serve real assets normally and return index.html for application routes such as /projects/orbit or /invoices/inv-1042. Confirm that directly opening and refreshing a detail URL works.

Subdirectory hosting requires coordinating Vite’s base, React Router’s basename in src/main.tsx, root-relative asset URLs and host rewrites. Changing only the Vite base is insufficient. The build itself does not deploy anything.

SymptomWhat to check
504 Outdated Optimize Dep after dependency changesStop the dev server, run npm run dev -- --force, then reload.
Port already in useRun npm run dev -- --port 5175 --strictPort.
Another local application appearsUse the exact 127.0.0.1 URL printed by Vite.
Changed seed data does not appearReset sample data or use a fresh browser profile. Reset discards local edits.
Built preview shows old contentRun npm run build again before previewing.
Detail page returns 404 after deploymentCheck the host’s SPA fallback.
Changes disappear between visitsCheck browser storage availability and that you are using the same origin.

The persistence key is aerolaunch.forma.workspace.v1. The demo does not synchronize records across tabs, devices or accounts. Invalid saved data restores a fresh sample workspace with a notice.

For help, email hello@aerolaunch.app with your Forma version, Node version, browser, exact command or steps, and the error output. Include your Lemon Squeezy order reference for download questions.