Develop, debug, and share a Node.js app
Developer
This tutorial teaches you the everyday development loop in Citrix SecurSpaces™ by working through a real application. You run it, change it, debug it on both the server and the browser, catch mistakes before they reach the browser, and share the result with a teammate.
By the end, you will have:
- Started a PostgreSQL database and a Next.js application inside your workspace
- Changed the running application and watched it reload
- Inspected the same data through the browser, the API, and the database
- Paused server-side and browser-side code in a debugger
- Shared your running application with your project through a single URL
Every step builds on the one before it, so work through them in order. The whole tutorial takes about 30 minutes.
Before you begin
You need a running Hello World workspace, created as described in
Hello World workspace, with the five DB_*
secrets configured.
The Hello World container image is not available to every project by default. If you can’t find it when you create a workspace, ask your project owner to set up a Hello World playground project for your organization. The Hello World workspace article tells them what to add.
Open your Hello World workspace in the Cloud IDE (VS Code for Web) before you start Step 1.
Step 1: Check your environment
Confirm your workspace has the tools and secrets this tutorial depends on. Open a terminal in the Cloud IDE and run:
node --version
yarn --version
<!--NeedCopy-->
Both commands print a version number. The exact versions don’t matter for this tutorial.
Now confirm the database credentials reached your workspace as environment variables:
echo $DB_HOST
echo $DB_PORT
echo $DB_NAME
echo $DB_USER
echo $DB_PASSWORD
<!--NeedCopy-->
These print localhost, 5432, project_acme, acme_user, and acme_password.
If any of them print an empty line, the secrets weren’t added when the workspace was created. Return to Hello World workspace, Step 1, add the five secrets, and restart the workspace before continuing.
Notice that you didn’t create a .env file. SecurSpaces injects secrets into the workspace as environment
variables, so the application finds them without any local configuration.
Step 2: Start the database
The application stores its users in PostgreSQL, which runs in a Docker container inside your workspace. Start it before the application, or the first page load fails.
cd /home/developer/demo-nodejs-postgresql-main
docker-compose up -d
<!--NeedCopy-->
The first run downloads nothing — the image is already in the workspace — and initializes the database
schema from init.sql. It takes a few seconds.
Confirm the container is running:
docker ps
<!--NeedCopy-->
The output lists a container named project-acme-db with a status beginning with Up. If the list is
empty, run docker-compose up -d again and read any error it prints.
Step 3: Run the application
With the database up, start the development server from the same directory:
yarn dev
<!--NeedCopy-->
VS Code detects that the application opened a port and shows a notification: A workspace application is available at the port 3000. Select Preview.

The ACME Project user management application opens in an editor tab beside your code. The preview address
follows the pattern https://<workspace-id>-port-3000.proxy.<domain>, so the application is reachable
through the platform rather than from your own machine.
Select Users in the navigation bar, then add a user. The page saves it and shows it in the list.
You have just exercised the whole stack: the React page called the API, the API wrote to PostgreSQL, and the result came back to the browser. Keep this user — you look at it again in Step 5.
Leave yarn dev running.
Step 4: Make a change
Change the application while it runs, and watch the result appear without a restart.
- In the Cloud IDE, open
src/app/page.tsx. - Find the page heading and change its text. For example, change it to
Welcome to My ACME Project. - Save the file.
The preview tab updates within a few seconds. You didn’t restart the server, and you didn’t rebuild anything — the development server detected the change and reloaded the page for you.
This is the loop you spend most of your day in: edit, save, look. It behaves exactly as it does on a local machine.
Step 5: Look inside the database
The user you added in Step 3 is a real row in a real database. Open a second terminal so the development server keeps running in the first one, then connect to PostgreSQL:
docker exec -it project-acme-db psql -U acme_user -d project_acme
<!--NeedCopy-->
Notice that the prompt changes: you’re now typing into PostgreSQL, not into the shell. List the users:
SELECT * FROM users;
<!--NeedCopy-->
Your user from Step 3 appears in the results, alongside the sample users the schema created. The browser page, the API route, and this table are three views of the same data.
Leave PostgreSQL and return to the shell:
\q
<!--NeedCopy-->
Step 6: Debug the API
Now pause the server-side code while a request runs through it.
The debugger needs to start the application itself, so first stop the development server you started in
Step 3. Select the terminal running yarn dev and press Ctrl+C.
- Open
src/app/api/users/route.ts. - Find the
GETfunction and select the gutter to the left of a line inside it. A red dot marks the breakpoint. - Open a new terminal and choose JavaScript Debug Terminal from the terminal type list.
-
In that terminal, start the application again:
cd /home/developer/demo-nodejs-postgresql-main yarn dev <!--NeedCopy--> - Open the preview and select Users.
Execution stops at your breakpoint and the Cloud IDE switches to the debugging view. Expand the result
variable and open result.rows to see the records PostgreSQL returned — including the user you added.
Select Continue to let the request finish. The Users page then renders as usual.
Notice that you opened the Users page rather than the home page. The home page is static and never calls the API, so a breakpoint in the API route would never be reached from it.
Remove the breakpoint by selecting the red dot again, and leave the debug terminal running.
Step 7: Debug in the browser
Server-side code isn’t the only place a problem hides. This step debugs code running in the browser, which needs a different tool.
The application has a Slow switch that delays each API call by two to three seconds in the browser. It’s built for testing loading states.
- Copy the preview address and open it in a browser tab. The built-in Simple Browser in the Cloud IDE has no developer tools, so this step needs a real tab.
- Select the Slow switch in the navigation bar.
- Open your browser’s developer tools by pressing F12, and select the Network tab.
- Reload the Users page. Each
/api/usersrequest now takes two to three seconds. - Select the Fast switch and reload again. The delay is gone.
To pause inside the delay itself, select the Sources tab, open src/app/utils/delay.ts, and set a
breakpoint inside simulateDelay. Reload the Users page. Execution pauses, and you can inspect
isSlowMode and slowDelay.
You have now used both debuggers: the JavaScript Debug Terminal for code running on the server, and your browser’s developer tools for code running in the page.
Step 8: Catch errors before you run the code
Two checks find mistakes without starting the application at all.
First, introduce a type error. Open src/app/api/users/route.ts, change a string parameter to number,
and save. Then run:
yarn type-check
<!--NeedCopy-->
The command fails and names the file, the line, and the mismatch. Change the parameter back and run
yarn type-check again — it passes silently.
Now introduce a lint error. Add an unused variable to any .ts file, such as const unused = 1;, and save.
Then run:
yarn lint
<!--NeedCopy-->
The unused variable is reported. Remove it and run yarn lint again to confirm the project is clean.
Both checks run against your code, not against a running server, so they catch mistakes in seconds.
Step 9: Share the running app
Finally, let someone else open your work without cloning anything or waiting for a deployment.
Make sure yarn dev is still running, then:
- In the SecurSpaces console, open the Project Overview page.
- From the Workspace Apps menu, select Create Workspace App.
- Enter these values:
-
Port:
3000 -
Name:
ACME Project - Share: Project Sharing
-
Port:
- Select Save.
The console shows a URL for the application. Copy it and send it to a project member. They open it in a browser and use the application you are running, without a workspace of their own.
When you finish, delete the workspace app to stop sharing.
What you have learned
You ran a full-stack application inside a workspace, and everything behaved the way it does on a local machine — the same commands, the same debugger, the same browser tools. What changed is where the code runs and where the data stays.
Along the way you:
- Confirmed that secrets arrive as environment variables, with no
.envfile to manage - Started a database with Docker inside your workspace
- Used hot reload, a server-side debugger, and browser developer tools
- Ran type checking and linting
- Shared a running application through a URL instead of a deployment
What to do next
| Goal | Guide |
|---|---|
| Apply these workflows to your own project | Develop in a workspace |
| Understand what survives a workspace restart | What persists in a SecurSpaces Workspace |
| Set up your real project environment | Set up your account |
| Learn more about sharing a running application | Workspace Apps |
Get help
- Ask your project owner about template contents, missing tools, or database access.
- Browse the SecurSpaces documentation for detailed guides.
In this article
- Before you begin
- Step 1: Check your environment
- Step 2: Start the database
- Step 3: Run the application
- Step 4: Make a change
- Step 5: Look inside the database
- Step 6: Debug the API
- Step 7: Debug in the browser
- Step 8: Catch errors before you run the code
- Step 9: Share the running app
- What you have learned
- What to do next
- Get help