How to manually deploy upgradeable smart contract without using hardhat-upgrades?

Hi. Below example showing us how to deploy upgradeable smart contract using hardhat plugin. As I know the plugin do some stuff in the background, so i want to know if I'm able to do the same things manually for better understanding. Can I achieve that? Thanks ..

// scripts/create-box.js
const { ethers, upgrades } = require("hardhat");

async function main() {
  const Box = await ethers.getContractFactory("Box");
  const box = await upgrades.deployProxy(Box, [42]);
  await box.deployed();
  console.log("Box deployed to:", box.address);
}

main();

You can find some examples in the hardhat plugin's test cases where proxies are deployed "manually".

Note that the plugin also validates your implementation for upgrade safety, aside from helping with proxy deployment. You could run the validations separate from deployments with the validateImplementation and validateUpgrade functions.

Thank you ericglau for your response. So when we use uups upgradeable proxy from openzeppelin what actually happens is that it will deploy the implementation contract first, then the ERC1967Proxy contract, right?

Yes, that is correct when you use the Upgrades plugin.

Alright, thank you so much