> ## Documentation Index
> Fetch the complete documentation index at: https://docs.near.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating a Frontend

> Lets create a frontend for our auction using React.

export const Github = ({url, start, end, fname, withSourceLink = true}) => {
  const [code, setCode] = useState(null);
  function toRaw(ref) {
    const fullUrl = ref.slice(ref.indexOf('https'));
    const [url] = fullUrl.split('#');
    const [org, repo, , branch, ...pathSeg] = new URL(url).pathname.split('/').slice(1);
    return `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${pathSeg.join('/')}`;
  }
  async function fetchCode(url, fromLine, toLine) {
    let res;
    if (typeof window !== 'undefined') {
      const validUntil = localStorage.getItem(`${url}-until`);
      if (validUntil && Number(validUntil) > Date.now()) {
        res = localStorage.getItem(url);
      }
    }
    if (!res) {
      try {
        res = await (await fetch(url)).text();
        if (typeof window !== 'undefined') {
          localStorage.setItem(url, res);
          localStorage.setItem(`${url}-until`, String(Date.now() + 60000));
        }
      } catch {
        return 'Error fetching code, please try reloading';
      }
    }
    let body = res.split('\n');
    const from = fromLine ? Number(fromLine) - 1 : 0;
    const to = toLine ? Number(toLine) : body.length;
    body = body.slice(from, to);
    const precedingSpace = body.reduce((prev, line) => {
      if (line.length === 0) return prev;
      const spaces = line.match(/^\s+/);
      if (spaces) return Math.min(prev, spaces[0].length);
      return 0;
    }, Infinity);
    return body.map(line => line.slice(precedingSpace === Infinity ? 0 : precedingSpace)).join('\n');
  }
  function buildSourceUrl(url, start, end) {
    const base = url.split('#')[0];
    if (start && end) return `${base}#L${start}-L${end}`;
    if (start) return `${base}#L${start}`;
    return base;
  }
  useEffect(() => {
    const rawUrl = toRaw(url);
    fetchCode(rawUrl, start, end).then(res => setCode(res));
  }, [url, start, end]);
  const sourceUrl = buildSourceUrl(url, start, end);
  const startLine = start ? Number(start) : 1;
  const fileName = fname ?? sourceUrl.split('/').pop();
  return <div className="rounded-[0.625rem] border border-[#d0d7de] dark:border-[#30363d] overflow-hidden my-5 text-[0.8125rem] font-mono shadow-sm dark:shadow-[0_4px_24px_rgba(0,0,0,0.18)]">

      {}
      <div className="flex items-center justify-between py-2 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-b border-[#d0d7de] dark:border-[#30363d]">
        <div className="flex items-center gap-2 text-[#656d76] dark:text-[#8b949e]">
          <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
            <path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
          </svg>
          <span className="text-xs font-medium text-[#1f2328] dark:text-[#e6edf3]">
            {fileName}
          </span>
        </div>
        {start && end && <span className="text-[0.6875rem] text-[#656d76] dark:text-[#8b949e] bg-[#eaeef2] dark:bg-[#21262d] border border-[#d0d7de] dark:border-[#30363d] rounded-full py-0.5 px-2">
            Lines {start}–{end}
          </span>}
      </div>

      {}
      <div className="overflow-auto max-h-[480px] bg-white dark:bg-[#0d1117] [&_tr]:border-b-0 [&_td]:border-b-0">
        {code === null ? <div className="py-5 px-4 text-xs text-[#656d76] dark:text-[#6e7681]">
            Loading...
          </div> : <table className="w-full border-collapse leading-[1.6]">
            <tbody>
              {code.split('\n').map((line, i) => <tr key={i} className="align-top border-0">
                  <td style={{
    minWidth: '60px'
  }} className="select-none pl-2 pr-3 text-right text-[0.7rem] text-[#8c959f] dark:text-[#3d444d] w-[1%] whitespace-nowrap border-r border-0 border-r-[#d0d7de] dark:border-r-[#21262d]">
                    {startLine + i}
                  </td>
                  <td className="pl-4 pr-6 text-[0.8125rem] text-[#1f2328] dark:text-[#e6edf3] whitespace-pre">
                    {line || ' '}
                  </td>
                </tr>)}
            </tbody>
          </table>}
      </div>

      {}
      {withSourceLink && <div className="flex justify-end py-1.5 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-t border-[#d0d7de] dark:border-[#21262d]">
          <a href={sourceUrl} target="_blank" rel="noreferrer noopener" className="text-[0.6875rem] font-medium text-[#656d76] dark:text-[#8b949e] no-underline flex items-center gap-[0.3rem] hover:text-[#1f2328] dark:hover:text-[#e6edf3] transition-colors">
            View on GitHub
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
              <polyline points="15 3 21 3 21 9" />
              <line x1="10" y1="14" x2="21" y2="3" />
            </svg>
          </a>
        </div>}
    </div>;
};

Now that we have successfully created a contract, it's time to build a frontend to provide a user-friendly interface for interacting with it. Up until now, we have been using the CLI to send transactions and view the contract's state. However, frontends offer a more intuitive way for end users to interact with the contract. They can display all the relevant information in one place, allow users to make calls with a simple button click, and only require a wallet as a prerequisite.

***

## Frontend structure

Navigate to the auction frontend.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
cd frotends/01-frontend
```

Here we have a simple Next.js frontend that we'll walk through to understand the basics of creating a frontend for a NEAR smart contract.

For starters, let's take a look at how the code in the frontend is structured by doing a quick overview of the important files.

| File               | Description                                                                                                                                                                        |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **\_app.js**       | Responsible for rending the page, initiates the wallet object and adds it to global context                                                                                        |
| **index.js**       | The main page where the project's components are loaded into and contains most of the logic for the application like viewing the state of the contract and logic for placing a bid |
| **near.js**        | Contains the wallet class that has methods to interact with the wallet and blockchain                                                                                              |
| **context.js**     | Holds the global context - the wallet object and the signed-in account ID - that can be accessed anywhere                                                                          |
| **config.js**      | Specifies the account ID of the auction contract                                                                                                                                   |
| **Navigation.jsx** | A component that contains a button to sign users in and out of wallets                                                                                                             |
| **Bid.jsx**        | A component allowing a user to make a bid                                                                                                                                          |
| **LastBid.jsx**    | A component that displays the highest bid and when the highest bid will next refresh                                                                                               |
| **Timer.jsx**      | A component that shows how long till the auction is over, or, if over, displays a button to claim the auction and then states the auction is over                                  |

***

## Specifying the contract

We have a config file that specifies the contract name of the auction that the frontend will interact with. There has been an example auction contract deployed and specified already but feel free to change the contract to your own auction contract you deployed.

<Github fname="config.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/config.js" />

***

## Setting up wallets

To be able to fully interact with the contract - send bids and claim the auction - you'll need a `wallet` to sign transactions. Wallets securely store your private keys and allow you to sign transactions without exposing your private key to the frontend. The wallet selector allows users to choose between a selection of wallets.

We abstract the wallet selector in our `near.js` file by exposing methods to complete various tasks. Feel free to [explore the file](https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/wallets/near.js) to understand fully how the wallet selector is implemented.

The wallet object is initiated in the `app.js` file and its added to the global context along with the account that is signed in to make it easier to access anywhere in the application.

<Github fname="_app.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/pages/_app.js#L13-L27" start="13" end="27" />

<Github fname="context.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/context.js" />

<Tip>
  **Access keys**

  On NEAR, in additional to normal full access keys, we have `function-call access keys` that are given to applications to allow them to sign `non-payable` transactions on behalf of the user. This is so the wallet doesn't have to pop up for each non-critical transaction, improving the user experience. When creating the wallet object you can decide to create an access key for the application to use. However, in this example we opt out since the main function - `bid` - we'll be calling is `payable`.

  You can read further about NEAR's key model [here](/protocol/accounts-contracts/access-keys).
</Tip>

We add a sign-in and sign-out button in the `navigation` component to call the respective methods in the `near.js` file.

<Github fname="Navigation.jsx" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/components/Navigation.jsx" />

<Github fname="near.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/wallets/near.js#L58-L72" start="58" end="72" />

***

## Displaying the highest bid

To get the highest bid from the auction and who made it we call `get_highest_bid`. Since this function returns the highest bid in `yoctoNEAR` we divide by `10^24` to get the amount in NEAR.

<Github fname="index.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/pages/index.js#L24-L29" start="24" end="29" />

<Github fname="near.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/wallets/near.js#L82-L94" start="82" end="94" />

In the wallet file, you'll see that we make a query to the RPC provider, since we are not signing a transaction the wallet isn't required here. Here we are using [https://rpc.testnet.near.org](https://rpc.testnet.near.org) but note there are [many different providers available](/api/rpc/providers). We are querying the RPC with optimistic finality, which queries the latest block recorded on the node. Alternatively, one could use final finality where the block has been validated by at least 66% of the validators on the network but this will provide slightly delayed information (only by a couple of seconds).

We then pass the information about the highest bidder into the `LastBid` component to display the bid amount and the bidder's account Id.

<Github fname="index.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/pages/index.js#L101" start="101" end="101" />

<Github fname="LastBid.jsx" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/components/LastBid.jsx" />

***

## Updating the highest bid

We want to know the highest bid at all times, someone else could have placed a higher bid since the page was loaded. To solve this we fetch the contract information every 20 seconds using `setInterval` and update the highest bid if it has changed. In reality you would want to refresh the bid amount more requently but for the sake of saving on RPC calls we are doing it every 20 seconds.

<Github fname="index.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/pages/index.js#L47-L60" start="47" end="60" />

***

## Auction end time

The contract stores the end time of the auction in the number of nanoseconds since the Unix epoch (1 January 1970 00:00:00 UTC). In our frontend we will display the time left in days, hours, minutes, and seconds.

<Github fname="Timer.jsx" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/components/Timer.jsx#L11-L35" start="11" end="35" />

***

## Making a bid

To make a bid we make a call to the contract using the `bid` function. We specify the deposit amount in `yoctoNEAR` which will be the bid amount. The input box will take the bid amount in NEAR so we multiply by `10^24` to get the correct amount to send. We also specify the amount of gas to attach to the transaction, here we are attaching 30Tgas which is more than enough for the transaction to go through, we are refunded any unused gas anyway.

Here, since the user is changing the state of the contract, not just viewing it, the user needs to sign the transaction. Thus the wallet will pop up displaying the transaction details.

<Github fname="index.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/pages/index.js#L95-L105" start="95" end="105" />

<Github fname="near.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/wallets/near.js#L107-L126" start="107" end="126" />

***

## Claiming the auction

Once the auction is over (the current time is greater than the end time) the auction can be claimed. At this point, the timer will be hidden and a button to claim the auction will be displayed. Once clicked the `claim` function will be called on the auction contract to send the highest bidder the NFT and the auctioneer the FTs.

<Github fname="index.js" url="https://github.com/near-examples/auctions-tutorial/blob/main/frontends/01-frontend/src/pages/index.js#L75-L82" start="75" end="82" />

***

## Conclusion

In this part of the tutorial, we have implemented a simple frontend for a NEAR contract. Along the way, you have learned how to use the wallet selector to sign the user in and out, how to view the contract’s state, how to sign and send transactions.

While we can see the highest bid, we may want to see the auction's bidding history. Since the contract only stores the most recent bid (to reduce storage costs), we need to use an indexer to pull historical data. In the [next part](./2.2-indexing) of the tutorial, we'll look at querying historical data using an API endpoint.
