What you want to do is take advantage of Sitecore's branching functionality. A branch in Sitecore is basically a prebuilt item tree that will be copied and inserted where you want it. It could be one item or a thousand items.
In your case, what it helps you do is to build out a page, with all the related data folders under the page. All delivered in an insert option for your items.
Create branch
Under the item /sitecore/templates/Branches/
insert a new branch item. This will prompt you to pick a template to base this branch on. Here you would pick you page template that you want to create. Once complete, edit this new page in the experience editor just like you would in your site tree. Add you components, any default content you need, etc... During this process you will create any sub items that are needed as data sources for the item.
Once complete, you will have a new page exactly as you want it to be created in your site. It should look like the image below.
Add as insert option for your site
One of the best parts of a branch is that you can add it to insert options just like any other item. What ever item you want to have this as an insert option, edit the insert options and select the branch item you just created. Do not select the $name item, but its parent which is the branch item. The $name item is the item that will be created.
NOTE: I always update my branch item to have the same icon as the item it is creating. This makes the visual experience the same and no one knows it is a branch item and not the original item.
Create a new item
Using the insert options you set above, insert a new item like normal. Once complete, the item and all its children will be created. Matching your branch item 1 for 1.
I am not sure when Sitecore added it to the base, but in Sitecore 9 all of the rendering datasources are updated automatically. This allows for every new item to reference its own sub items for datasources with no intervention required from the editors. If this does not happen for you, just use Kam's branch presets. This will do the exact same thing.
https://github.com/kamsar/BranchPresets
That's it. You can now use this same process to create as many pre-built pages as your editors need.
Alternative, Use a command template to create the branch and do the work.
public class CreateSite : Command
{
//protected void CreateSite()
//{
// //Change the eventName here
// SheerResponse.Timer("multisite:createSiteA", 100);
//}
public static string InvalidPath = "/sitecore/templates/Branches/Project/Common/Sites/Site Root";
public override void Execute(CommandContext context)
{
if (context.Items.Length == 1)
{
var item = context.Items[0];
var parameters = new NameValueCollection();
parameters["id"] = item.ID.ToString();
parameters["language"] = item.Language.ToString();
parameters["database"] = item.Database.Name;
Sitecore.Context.ClientPage.Start(this, "Run", parameters);
}
}
protected void Run(Sitecore.Web.UI.Sheer.ClientPipelineArgs args)
{
if (!args.IsPostBack)
{
//Means we are in the initial step, we want to ask for the name of the news
Sitecore.Context.ClientPage.ClientResponse.Input("Enter site name:",
Sitecore.Globalization.Translate.Text("Site Name"),
Sitecore.Configuration.Settings.ItemNameValidation, "'$Input' is not a valid name.", 100);
args.WaitForPostBack();
}
else
{
//Now we got a postback, which means we got a response
if (!String.IsNullOrEmpty(args.Result) && args.Result != "undefined")
{
var db = Sitecore.Configuration.Factory.GetDatabase(args.Parameters["database"]);
var parent = db.GetItem(args.Parameters["id"], Language.Parse(args.Parameters["language"]));
BranchItem branch = parent.Database.GetItem(Constants.BranchSite.SiteA);
var item = parent.Add(args.Result, branch);
// DO YOUR WORK HERE
Sitecore.Context.ClientPage.SendMessage(this, "item:load(id=" + item.ID + ")");
}
}
}
}