Skip to content

Commit 3e289a7

Browse files
committed
Add Websites guide
1 parent 01bff0f commit 3e289a7

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

docs/guides/nodejs/survey-website.mdx

+235
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
---
2+
description: Create a React frontend that submits data to backend that generates, stores and retrieves receipts.
3+
title_seo: Build a Frontend for Your Nitric Survey App
4+
tags:
5+
- React
6+
- Websites
7+
- API
8+
languages:
9+
- javascript
10+
- typescript
11+
published_at: 2025-04-03
12+
updated_at: 2025-04-03
13+
---
14+
15+
# Build a Frontend for Your Nitric Survey App with React
16+
17+
In this guide, you’ll build a simple web application using React that connects to the survey backend we created with Nitric.
18+
19+
## What You'll Build
20+
21+
- A form to submit survey responses to the Nitric backend
22+
- A link to retrieve and view the submitted PDF receipt
23+
24+
## Prerequisites
25+
26+
- [Node.js](https://nodejs.org/en/download/)
27+
- The [Nitric survey backend project](./surveys-application)
28+
29+
## Project Setup
30+
31+
This guide assumes you already have the [survey backend project](./surveys-application).
32+
33+
To add a website frontend, create a new Vite project:
34+
35+
```bash
36+
npm create vite@latest main-website -- --template react-ts
37+
cd main-website
38+
npm install
39+
cd ..
40+
```
41+
42+
Next, configure your `nitric.yaml` to enable and configure the website:
43+
44+
```yaml title:nitric.yaml
45+
name: survey-app
46+
services:
47+
- basedir: ''
48+
match: services/*.ts
49+
runtime: node
50+
start: npm run dev:services $SERVICE_PATH
51+
batch-services: []
52+
websites:
53+
- basedir: ./main-website
54+
error: index.html
55+
build:
56+
command: npm run build
57+
output: dist
58+
dev:
59+
command: npm run dev -- --port 3000
60+
url: http://localhost:3000
61+
runtimes:
62+
node:
63+
dockerfile: ./node.dockerfile
64+
context: ''
65+
args: {}
66+
preview:
67+
- websites
68+
```
69+
70+
## Connect to the API
71+
72+
Create a new folder `components` inside `main-website/src` and add the following file:
73+
74+
This component collects the user's name, rating, and feedback, then submits the data to the Nitric API.
75+
76+
```tsx title:main-website/src/components/SurveyForm.tsx
77+
import React, { useState } from 'react'
78+
79+
const SurveyForm = () => {
80+
const [formData, setFormData] = useState({
81+
name: '',
82+
rating: 1,
83+
feedback: '',
84+
})
85+
const [submissionId, setSubmissionId] = useState<string | null>(null)
86+
87+
const handleChange = (
88+
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
89+
) => {
90+
setFormData({ ...formData, [e.target.name]: e.target.value })
91+
}
92+
;<button
93+
onClick={async () => {
94+
try {
95+
const response = await fetch(`/api/forms/receipts/${submissionId}`)
96+
if (!response.ok) {
97+
throw new Error('Could not get receipt URL')
98+
}
99+
const { url } = await response.json()
100+
window.location.href = url // behaves like a 303 redirect
101+
} catch (err) {
102+
console.error(err)
103+
alert('Failed to load receipt')
104+
}
105+
}}
106+
>
107+
View Receipt
108+
</button>
109+
110+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
111+
e.preventDefault()
112+
try {
113+
const response = await fetch('/api/forms/forms/test-survey', {
114+
method: 'POST',
115+
headers: {
116+
'Content-Type': 'application/json',
117+
},
118+
body: JSON.stringify(formData),
119+
})
120+
121+
if (!response.ok) {
122+
throw new Error('Network response was not ok')
123+
}
124+
125+
const data: { id: string } = await response.json()
126+
setSubmissionId(data.id)
127+
alert('Survey submitted successfully!')
128+
} catch (error) {
129+
console.error('Error submitting survey:', error)
130+
alert('Failed to submit survey.')
131+
}
132+
}
133+
134+
return (
135+
<div>
136+
<h2>Survey</h2>
137+
<form onSubmit={handleSubmit}>
138+
<div>
139+
<label>Name:</label>
140+
<input
141+
type="text"
142+
name="name"
143+
value={formData.name}
144+
onChange={handleChange}
145+
required
146+
/>
147+
</div>
148+
<div>
149+
<label>Rating (1–5):</label>
150+
<input
151+
type="number"
152+
name="rating"
153+
value={formData.rating}
154+
onChange={handleChange}
155+
min="1"
156+
max="5"
157+
required
158+
/>
159+
</div>
160+
<div>
161+
<label>Feedback:</label>
162+
<textarea
163+
name="feedback"
164+
value={formData.feedback}
165+
onChange={handleChange}
166+
/>
167+
</div>
168+
<button type="submit">Submit</button>
169+
</form>
170+
171+
{submissionId && (
172+
<div>
173+
<p>Submission ID: {submissionId}</p>
174+
<button
175+
onClick={async () => {
176+
try {
177+
const response = await fetch(
178+
`/api/receipts/receipts/${submissionId}`,
179+
)
180+
if (!response.ok) {
181+
throw new Error('Could not get receipt URL')
182+
}
183+
const url = await response.text()
184+
window.location.href = url
185+
} catch (err) {
186+
console.error(err)
187+
alert('Failed to load receipt')
188+
}
189+
}}
190+
>
191+
View Receipt
192+
</button>
193+
</div>
194+
)}
195+
</div>
196+
)
197+
}
198+
199+
export default SurveyForm
200+
```
201+
202+
### Add the component to your app
203+
204+
Update the following file to use your new form component:
205+
206+
```tsx title:main-website/src/App.tsx
207+
import React from 'react'
208+
import SurveyForm from './components/SurveyForm'
209+
210+
function App() {
211+
return (
212+
<div>
213+
<SurveyForm />
214+
</div>
215+
)
216+
}
217+
218+
export default App
219+
```
220+
221+
## Run the Frontend Locally
222+
223+
With your `nitric.yaml` configured correctly and the site added as a Nitric website, you can start both the frontend and backend using:
224+
225+
```bash
226+
nitric start
227+
```
228+
229+
This will start the API and the website together, and serve your React frontend from [http://localhost:5000](http://localhost:5000) (confirm the port in the console output).
230+
231+
To test it, visit [http://localhost:5000](http://localhost:5000) in your browser and submit a survey response. You should see a link to view the generated receipt hosted by the backend.
232+
233+
## Conclusion
234+
235+
Serving your React frontend and Nitric backend under the same origin, both locally and in the cloud, eliminates CORS issues and removes the need for headers, complex gateway config, or workarounds.

0 commit comments

Comments
 (0)