Skip to content

Step 1: Getting Started with Widget Development

Welcome to widget development! In this step, you’ll set up your development environment and get familiar with the widget development workflow.

🎯 What You’ll Accomplish

By the end of this step, you’ll have:

  • Development environment ready - All prerequisites installed and configured
  • Widget starter kit cloned - Your own copy of the widget template
  • Development server running - Local widget development environment active
  • Project structure understanding - Know how widget projects are organized

🏒 Check With Your Organization First

Before diving into the standard tools, check with your platform team to see if your organization provides:

  • Custom widget starter kit - Organization-specific template with company standards
  • Internal development guidelines - Company-specific setup instructions
  • Custom development tools - Organization-specific CLI tools or workflows
  • Internal widget registry - Private package registry for dependencies

If your organization has custom tools, use those instead! The concepts in this tutorial will still apply.

πŸ”§ Prerequisites Check

Ensure you have the following installed:

Node.js and Package Manager

Terminal window
# Check Node.js version (22+ required)
node --version
# Check yarn version(4.x.x)
yarn --version

πŸ“¦ Cloning the Widget Starter Kit

We’re going to clone the widget starter kit to begin developing your first widget.

Wait, what’s a widget? πŸ€” It’s a self-contained piece of JavaScript that runs in the 1fe ecosystem - like a mini-app! And the starter kit is your pre-configured template with all the tooling you need.

1. Clone the Repository

Terminal window
# Clone the widget starter kit
git clone https://github.com/docusign/1fe-widget-starter-kit.git my-first-widget
# Navigate to the project
cd my-first-widget

2. Install Dependencies

Terminal window
# Install all dependencies
yarn install

This will install all the necessary dependencies for widget development

3. Explore the Project Structure

Let’s understand what you just cloned:

my-first-widget/
β”œβ”€β”€ src/ # Your widget source code
β”‚ β”œβ”€β”€ components/ # Reusable React components
β”‚ β”œβ”€β”€ contract.ts # Widget contract definition
β”‚ β”œβ”€β”€ app1.tsx # Main widget entry point
β”‚ └── widget.ts # Default widget export
β”œβ”€β”€ tests/ # Test files
β”œβ”€β”€ .1fe.config.ts # Widget build and runtime configuration
β”œβ”€β”€ package.json # Dependencies and scripts
└── README.md # Project documentation

πŸ—οΈ Understanding Key Files

Widget Entry Point (src/app1.tsx)

This is your main widget component:

src/app1.tsx
import { platformProps } from "@1fe/shell";
import React, { useEffect } from "react";
import { Router as Widget } from "./components/router";
import { withProvider } from "./withProvider";
import { WidgetProps } from "./contract";
const RootWrapper: React.FC<WidgetProps> = (props) => {
useEffect(() => {
platformProps.utils.appLoadTime.end();
console.log("props", props);
}, []);
return <Widget {...props} />;
};
export default withProvider(RootWrapper);

Notice that platformProps in there? That’s your widget’s toolkit - built-in utilities for things like app load time tracking, context management, event communication, and more! 🧰 Discover all the cool utilities you get for free.

Widget Contract (src/contract.ts)

This is your widget contract - it defines what data your widget expects to receive and what it promises to provide. Think of it as the β€œhandshake” between your widget and the platform. Curious about how contracts work? 🀝

src/contract.ts
import { PlatformPropsType } from "@1fe/shell";
export type HostPropsContract = Record<string, unknown>;
export type WidgetProps = {
host: HostPropsContract;
platform: PlatformPropsType;
};

Configuration (.1fe.config.ts)

This little file is actually quite powerful - it controls how your widget is built, bundled, and deployed! It tells the 1fe CLI how to process your widget and what dependencies it needs. Want to know what else it can do? βš™οΈ

.1fe.config.ts
import { OneFeConfiguration } from "@1fe/cli";
import { getBaseConfig } from "@1fe/sample-widget-base-config"; // this is the redistributed package for the organization
const configuration: OneFeConfiguration = {
baseConfig: getBaseConfig,
};
export default configuration;

πŸš€ Starting the Development Server

Now let’s get your widget running locally:

Terminal window
# Start the development server
yarn dev

You should see output similar to:

βœ” Webpack
Compiled successfully in 3.82s
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://127.0.0.1:8080/
<i> [webpack-dev-server] 404s will fallback to '/index.html'
post action hook executed
[dev] Opening the widget in the playground with the URL:
http://localhost:3001/playground?widgetUrl=http%3A%2F%2F127.0.0.1%3A8080%2Fjs%2F1fe-bundle.js

And there it is - your widget will open in the 1fe Playground! The playground is a development sandbox that provides an isolated environment for testing widgets without needing the full application setup. Think of it as your widget’s sandbox where it can play safely. Want to explore what the playground can do? πŸ›

What just happened?

  • The 1fe CLI compiled your widget
  • Started a local development server
  • Made your widget available at a local URL
  • Enabled hot reloading for development

πŸ” Verifying Your Setup

Let’s make sure everything is working:

1. Check the Bundle URL

Open your browser and visit:

http://localhost:8080/js/1fe-bundle.js

You should see JavaScript code (the compiled widget bundle).

2. Open in playground

If your team doesn’t have their own 1fe instance, you can open the widget in our demo 1fe instances playground by visiting:

http://demo.1fe.com/playground?widgetUrl=http%3A%2F%2F127.0.0.1%3A8080%2Fjs%2F1fe-bundle.js

3. Make a Test Change

Edit src/app1.tsx and change the heading:

src/app1.tsx
import { platformProps } from "@1fe/shell";
import React, { useEffect } from "react";
import { Alert } from "antd";
import { Router as Widget } from "./components/router";
import { withProvider } from "./withProvider";
import { WidgetProps } from "./contract";
const RootWrapper: React.FC<WidgetProps> = (props) => {
useEffect(() => {
platformProps.utils.appLoadTime.end();
console.log("Widget loaded with props:", props);
}, [props]);
return (
<div>
<Alert
message="πŸŽ‰ Widget Ready!"
type="success"
style={{ margin: "8px" }}
closable
/>
<Widget {...props} />
</div>
);
};
export default withProvider(RootWrapper);

Save the file and watch your terminal - you should see the widget recompile automatically and your browser should show a pretty banner at the top of the page with a close button.

πŸ“ Understanding Widget Architecture

Platform Integration

Your widget runs within the 1fe platform and has access to:

  • Platform utilities - Shared functions for logging, navigation, etc.
  • Shared dependencies - React, design systems, and common libraries
  • Shell context - Platform-wide state and configuration
  • Event system - Communication with other widgets and the shell

Development Workflow

The typical development cycle is:

  1. Code - Write widget functionality in src/
  2. Test - Use the playground for immediate feedback
  3. Build - Compile with yarn build:widget
  4. Deploy - Push to your organization’s deployment pipeline

πŸŽ‰ Success!

Congratulations! You now have a fully functional widget development environment. Your widget is compiled, served locally, and ready for development.

πŸ‘‰ Next Step

Now that your development environment is ready, let’s learn how to use the 1fe Playground to develop and test your widget interactively.

β†’ Step 2: Learn about the Playground

In the next step, we will explore the playground to learn more of it’s features.