We need to develop a SPA that allows us to collect customer information and offer free domain names for registration
Key features:
- A form for collecting input from the user, including their name and keywords related to their business
- A list of adjectives for combining with business keywords
- Make an API request to domainsdb.info to check availability
When developing a solution, we will be guided by the following principles
- Development speed - we want to create an application as soon as possible, for this we will use ready-made solutions as much as possible
- Simplicity - The solution should be easy to use, but at the same time customizable if necessary, for example, styles, texts
- Compatibility - the web application should be convenient to use both in the desktop and in the mobile version
- Usability - in the process of interacting with the application, the user has a clear idea of what is expected of him at every step
To achieve our goal consider the main ideas for the implementation of the task:
- The web application is a single page form with a set of fields and a step-by-step progress indicator
- By filling in the required form fields, the user will be able to choose any of the offered free domain names
- When the form is completely filled, the Submit button becomes active to save the result
For clarity, let's create layouts of the web application drawn in draw.io
We have the following items
- Title (optional)
- Subtitle (optional)
- Username - text field
- Key business words - multi-input with the ability to select existing keywords or add your own
- Company name - text field
- Step by step description of progress
- Submit button
- Company logo (optional)
As the form fills out, the user will see how his progress is changing and what steps are still left to achieve the goal
When the user fills in the field with the name of the company, the application will offer a list of available names, at this step the user can select a name or click on the "show more" button to see other options, or enter the name manually
When the domain name is selected, the form is considered fully completed and the user can submit it
First of all, let's describe the stack:
- XState - will help to effectively manage the state of the application
- ChakraUI - a set of ui components for React, will allow you to use ready-made components for buttons and form fields
- React-select - to provide multiselect functionality
- Next.js - will allow us to collect our page in statics, which will have a positive effect on the loading time of the application
- Typescript - strong typing will help to minimize the number of possible errors in the development process
Let's split the application into logical components with the following structure
- App
- UserForm
- DomainForm
- Progress
Our application state can be conditionally divided into global state
and local state
Global state
this part of state wi going to implement withXState
, it describes the state of entire application, in our case it will contain information about the state of all fields, the progress of filling out the form and its validityLocal state
this part of state will implement on pure React, it represents separate parts of the application state, containing, for example, intermediate states of the interface, such a state, for example, can be in theDomainForm
component that displays information about the status of the API request for domain availability and a list of available domains- Let's dive deeper into this question, the
DomainForm
component can have the following states:- Idle state - when you first open the application, this component does not contain information about available domains
- Name availability checking - when the user enters the company name, the component sends a request to check the name availability, at this moment the spinner is displayed
- Displaying a list of available names - after receiving a response from the server, the component displays a list of available options
- Manual name entring - if the user did not find a suitable name among the proposed ones, he can try to enter the desired name manually
- Selected domain name - when the user clicks on one of the suggested domain names or enters it manually, it is saved to the global state and displayed as selected
- Let's dive deeper into this question, the
Let's consider the shape of global state
in XState
terms
interface State {
user: string;
keywords: string[];
company: string;
domain: string;
}
const stateMachine = createMachine<State>({
id: "form",
initial: "formFilling",
context: {
user: "",
keywords: [],
company: "",
domain: "",
},
states: {
formFilling: {},
},
});
What should we do to make application state available on every application component? Of course, we can use the classic tool for this task - React context
According this great article we can achieve this in another way
The main idea is to transform our state machine into actor
– independent objects that hold their own state and respond to events.
And then we can import it as a service that will be available from any app component
Any changes of our state will envoy rerendering of the app
// state.ts
import { interpret } from "xstate";
export const stateService = interpret(stateMachine);
stateService.start();
There are several ways to publish an application.
https://nextjs.org/docs/deployment#vercel-recommended
https://nextjs.org/docs/deployment#nodejs-server
https://nextjs.org/docs/advanced-features/static-html-export
For the customer of the application, it means the possibility of customization:
- Site Title
- Heading
- Description
- Logo
- Styles
- Favicon
The user can customize if necessary
- Color scheme
- Typography
- Spacing
- etc view more in chakra docs
To do this, you need to make changes to the theme.ts file, according to the documentation https://chakra-ui.com/docs/theming/theme
The user has the ability to customize the text of the main title and subtitle, for this you need to make the appropriate changes to the file: public/app-config.json
{
"title": "Site title",
"heading": "App heading",
"description": "app subtitle"
}
To change the list of suggested keywords, edit the file public/keywords.json
In order to use a custom logo or favicon, the user can save it as a file in the png
format along the pathspublic/logo.png
and public/favicon.png
The changes you have made need to be added to git
git add . && git commit -m "Update app config"
And then push the changes to the repository if needed
git push origin main