
Notion
Notion
Notion Database Buttons: 6 Levels, Beginner to Advanced
Notion Database Buttons: 6 Levels, Beginner to Advanced
Notion Database Buttons: 6 Levels, Beginner to Advanced
Notion Database Buttons: 6 Levels, Beginner to Advanced

Six levels, from a Done button to replacing your formulas

Database buttons made my Notion system about ten times faster, and I know how that sounds. What does a button have to do with a page loading?
I will get to that at level six, because it is the whole reason I made this. But I want to build up to it properly, so if you are new to buttons you can follow along from zero.
Six levels. The first three are easy, so if you already use buttons a lot, skip ahead to five and six. That is where it gets interesting.
Level 1: Edit this page

The simplest thing a button can do. One click moves a task from To Do to Done.
In your Tasks database, add a new property and pick Button. Call it Done. Add an action, choose Edit and then This page, set Status to Done, and save.
That is the whole thing. Click it on any task and the status changes.
Level 2: Add a condition

Now the button only works when you want it to.
In my Books database I want the finished date to fill in, but only when the status is actually Finished. Not before.
Add a Button property called Finished. Add the condition Status is Finished. Then add the action, Edit and This page, and set End Date to Date triggered.
If the status is not Finished and you click it, nothing happens. Change the status, click again, and today's date appears.
Use Time triggered instead if you need the exact time, which matters for anything tracking durations.
Level 3: A formula inside the property

Here is where it starts being useful.
In my Punishments database, every punishment I owe gets paid off by clicking Done, which adds one to my done count. But once I do not owe anything, clicking should do nothing. The count should stop.
Make a Button called Done, action Edit then This page, and point it at the Done Count property. Switch that to a custom formula.
The obvious version looks like this.
This page.Done Count + 1
And it works, right up until you owe nothing and it keeps counting anyway. So you add the condition inside the formula.
if(This page.Debt > 0, This page.Done Count + 1, This page.Done Count)
If there is debt, add one. If not, write the same number back, so clicking changes nothing.
I tested this on my own strict challenge for processed sugar. I was on day 22, slipped back to day one, and owed a debt of one. Clicked the button, paid it, 300 push-ups done. Clicked again and nothing moved.
Level 4: Variables

That same Done button also stamps a Last Paid date. Which means it is checking the same condition twice, once for the count and once for the date. Write that condition out twice and you have two places to break it later.
So you define it once.
Add Define variables as the first action on the button. Make a variable called owes.
This page.Debt > 0
Then Edit and This page, and both properties just read that variable.
Done Count:
if(owes, This page.Done Count + 1, This page.Done Count)
Last Paid:
if(owes, now(), This page.Last Paid)
One rule, written once, reused in two properties.
This is the level that matters most, because everything from here on needs variables. Level five and six do not work without them.
Level 5: Edit a different page

Until now the button has only edited the page it sits on. It does not have to.
In my Weekly Report I attach a reward to the week. This week's is going out with the family. And I can only claim it if three things are true at once: I earned it by hitting more than 50% of my week's actions, the week is actually over, and I have enough coins to pay for it.
The button lives on the week. The checkbox it ticks lives on the reward.
Start with Define variables. First one is Reward, the reward linked to this week.
This page.Reward
⚠️ A thing that will catch you out. Variables in the same Define block cannot read each other. If you need one variable to use another, the second one goes in its own separate Define variables block. I hit this live and it is not obvious at all.
So in a second block, Enough Coins, which reaches into my character to check my coins against the reward's cost.
This page.Character.map(current.All time Coins).sum() >= This page.Reward.first().Cost
Then End Week.
This page.End Date <= today()
Now add the action, Edit, and here is the part people miss: pick Reward as the target, not This page. The variable shows up in the data source list as a page you can edit.
Set Reward Claimed to:
if(This page.Reward.first().Earned and Enough Coins and End Week, true, This page.Reward.first().Reward Claimed)
If all three are true, tick it. Otherwise write back whatever it already was, so nothing changes.
Earned there is a formula living in the Reward database itself. The button just reads it through the relation, which is worth knowing because it means your buttons and your formulas can share work rather than duplicating it.
Level 6: Use buttons instead of formulas
This is the one. This is why I made the video.
When I built Game Mode V3 inside my second brain, it was slow. Properly slow.
Take one token as an example, the comet. You earn it by going to your Battle Log every day and claiming it. Which means that page gets created around 300 times a year.
So my character had to walk every single one of those pages, check whether I had collected that day, then count how many comets I had earned, and the amount is different every day because it comes from a complex formula. Then it had to handle spending, because comets go out to challenges, to the exchange, to my companion. All of it in one formula.
Eleven seconds to load.
And that is one token. I also have XP, coins, keys, skills.
The fix
Instead of making the character count everything every time, I moved the counting into the button.
Now when I click claim, the button checks whether I am allowed to earn it, works out the amount once, and writes it into a plain number property on the character. The character does not calculate anything any more. It just reads a number.
That is the whole trick, and here is why it works: plain number properties do not slow Notion down. Complex formulas with map, filter and chains of relations do.
The calculation still happens. It just happens once, on a click, instead of every time the page loads.
The claim button


Define variables first. AddXP works out how much XP to give, and returns 0 if I already claimed today, if there is no date, or if the log is not from today.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.XP), 0)))
AddComet is the same checks for the comet. No XP means no comet.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.Comet), 0)))
Then I need what the character currently holds. CurXP and CurComet.
let(c, This page.Grind Pulse.first().Character.first().Battle XP, if(empty(c), 0, c))
let(c, This page.Grind Pulse.first().Character.first().Battle Comet, if(empty(c), 0, c))
Notice that chain. My Battle Log is not related to my character directly, so it goes through Grind Pulse to get there. Three relations deep. In a formula that would be painfully slow. In a button it runs once and it is fine.
And char, the character page itself.
This page.Grind Pulse.first().Character
Then Edit the char variable, and the two properties are just addition.
Battle Comet = AddComet + CurComet Battle XP = AddXP + CurXP
Finally Edit This page to lock it, so a second click pays nothing.
Points Claimed = if(empty(This page.Date), false, formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"))
⚠️ The order matters. Variables, then pay the character, then lock the page. Every variable is calculated before any edit runs, so locking last never breaks the payment, and clicking twice pays zero.
I use this same pattern everywhere now. Collect tokens on tasks, on books, on reviews. You cannot claim anything twice.
It was an overnight solution to a problem I had been living with for months, and I have never appreciated buttons the way I did that day.
Why buttons are underrated
Most people stop at level one. A button that ticks a box.
But once you understand that a button can carry conditions, hold variables, reach across relations and write to other pages, it stops being a shortcut and becomes somewhere you can move work to. And if your Notion system is slow, that is usually the fix. Not fewer pages. Less being recalculated every time you open something.
Learn them properly and you will build things you did not think Notion could do.
Every button in this article is from SB7 x Game Mode V3, the system I use to stay disciplined and turn my life into an RPG. It is also the system that taught me all of this, because it broke first.

→ Get SB7
Six levels, from a Done button to replacing your formulas

Database buttons made my Notion system about ten times faster, and I know how that sounds. What does a button have to do with a page loading?
I will get to that at level six, because it is the whole reason I made this. But I want to build up to it properly, so if you are new to buttons you can follow along from zero.
Six levels. The first three are easy, so if you already use buttons a lot, skip ahead to five and six. That is where it gets interesting.
Level 1: Edit this page

The simplest thing a button can do. One click moves a task from To Do to Done.
In your Tasks database, add a new property and pick Button. Call it Done. Add an action, choose Edit and then This page, set Status to Done, and save.
That is the whole thing. Click it on any task and the status changes.
Level 2: Add a condition

Now the button only works when you want it to.
In my Books database I want the finished date to fill in, but only when the status is actually Finished. Not before.
Add a Button property called Finished. Add the condition Status is Finished. Then add the action, Edit and This page, and set End Date to Date triggered.
If the status is not Finished and you click it, nothing happens. Change the status, click again, and today's date appears.
Use Time triggered instead if you need the exact time, which matters for anything tracking durations.
Level 3: A formula inside the property

Here is where it starts being useful.
In my Punishments database, every punishment I owe gets paid off by clicking Done, which adds one to my done count. But once I do not owe anything, clicking should do nothing. The count should stop.
Make a Button called Done, action Edit then This page, and point it at the Done Count property. Switch that to a custom formula.
The obvious version looks like this.
This page.Done Count + 1
And it works, right up until you owe nothing and it keeps counting anyway. So you add the condition inside the formula.
if(This page.Debt > 0, This page.Done Count + 1, This page.Done Count)
If there is debt, add one. If not, write the same number back, so clicking changes nothing.
I tested this on my own strict challenge for processed sugar. I was on day 22, slipped back to day one, and owed a debt of one. Clicked the button, paid it, 300 push-ups done. Clicked again and nothing moved.
Level 4: Variables

That same Done button also stamps a Last Paid date. Which means it is checking the same condition twice, once for the count and once for the date. Write that condition out twice and you have two places to break it later.
So you define it once.
Add Define variables as the first action on the button. Make a variable called owes.
This page.Debt > 0
Then Edit and This page, and both properties just read that variable.
Done Count:
if(owes, This page.Done Count + 1, This page.Done Count)
Last Paid:
if(owes, now(), This page.Last Paid)
One rule, written once, reused in two properties.
This is the level that matters most, because everything from here on needs variables. Level five and six do not work without them.
Level 5: Edit a different page

Until now the button has only edited the page it sits on. It does not have to.
In my Weekly Report I attach a reward to the week. This week's is going out with the family. And I can only claim it if three things are true at once: I earned it by hitting more than 50% of my week's actions, the week is actually over, and I have enough coins to pay for it.
The button lives on the week. The checkbox it ticks lives on the reward.
Start with Define variables. First one is Reward, the reward linked to this week.
This page.Reward
⚠️ A thing that will catch you out. Variables in the same Define block cannot read each other. If you need one variable to use another, the second one goes in its own separate Define variables block. I hit this live and it is not obvious at all.
So in a second block, Enough Coins, which reaches into my character to check my coins against the reward's cost.
This page.Character.map(current.All time Coins).sum() >= This page.Reward.first().Cost
Then End Week.
This page.End Date <= today()
Now add the action, Edit, and here is the part people miss: pick Reward as the target, not This page. The variable shows up in the data source list as a page you can edit.
Set Reward Claimed to:
if(This page.Reward.first().Earned and Enough Coins and End Week, true, This page.Reward.first().Reward Claimed)
If all three are true, tick it. Otherwise write back whatever it already was, so nothing changes.
Earned there is a formula living in the Reward database itself. The button just reads it through the relation, which is worth knowing because it means your buttons and your formulas can share work rather than duplicating it.
Level 6: Use buttons instead of formulas
This is the one. This is why I made the video.
When I built Game Mode V3 inside my second brain, it was slow. Properly slow.
Take one token as an example, the comet. You earn it by going to your Battle Log every day and claiming it. Which means that page gets created around 300 times a year.
So my character had to walk every single one of those pages, check whether I had collected that day, then count how many comets I had earned, and the amount is different every day because it comes from a complex formula. Then it had to handle spending, because comets go out to challenges, to the exchange, to my companion. All of it in one formula.
Eleven seconds to load.
And that is one token. I also have XP, coins, keys, skills.
The fix
Instead of making the character count everything every time, I moved the counting into the button.
Now when I click claim, the button checks whether I am allowed to earn it, works out the amount once, and writes it into a plain number property on the character. The character does not calculate anything any more. It just reads a number.
That is the whole trick, and here is why it works: plain number properties do not slow Notion down. Complex formulas with map, filter and chains of relations do.
The calculation still happens. It just happens once, on a click, instead of every time the page loads.
The claim button


Define variables first. AddXP works out how much XP to give, and returns 0 if I already claimed today, if there is no date, or if the log is not from today.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.XP), 0)))
AddComet is the same checks for the comet. No XP means no comet.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.Comet), 0)))
Then I need what the character currently holds. CurXP and CurComet.
let(c, This page.Grind Pulse.first().Character.first().Battle XP, if(empty(c), 0, c))
let(c, This page.Grind Pulse.first().Character.first().Battle Comet, if(empty(c), 0, c))
Notice that chain. My Battle Log is not related to my character directly, so it goes through Grind Pulse to get there. Three relations deep. In a formula that would be painfully slow. In a button it runs once and it is fine.
And char, the character page itself.
This page.Grind Pulse.first().Character
Then Edit the char variable, and the two properties are just addition.
Battle Comet = AddComet + CurComet Battle XP = AddXP + CurXP
Finally Edit This page to lock it, so a second click pays nothing.
Points Claimed = if(empty(This page.Date), false, formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"))
⚠️ The order matters. Variables, then pay the character, then lock the page. Every variable is calculated before any edit runs, so locking last never breaks the payment, and clicking twice pays zero.
I use this same pattern everywhere now. Collect tokens on tasks, on books, on reviews. You cannot claim anything twice.
It was an overnight solution to a problem I had been living with for months, and I have never appreciated buttons the way I did that day.
Why buttons are underrated
Most people stop at level one. A button that ticks a box.
But once you understand that a button can carry conditions, hold variables, reach across relations and write to other pages, it stops being a shortcut and becomes somewhere you can move work to. And if your Notion system is slow, that is usually the fix. Not fewer pages. Less being recalculated every time you open something.
Learn them properly and you will build things you did not think Notion could do.
Every button in this article is from SB7 x Game Mode V3, the system I use to stay disciplined and turn my life into an RPG. It is also the system that taught me all of this, because it broke first.

→ Get SB7
Six levels, from a Done button to replacing your formulas

Database buttons made my Notion system about ten times faster, and I know how that sounds. What does a button have to do with a page loading?
I will get to that at level six, because it is the whole reason I made this. But I want to build up to it properly, so if you are new to buttons you can follow along from zero.
Six levels. The first three are easy, so if you already use buttons a lot, skip ahead to five and six. That is where it gets interesting.
Level 1: Edit this page

The simplest thing a button can do. One click moves a task from To Do to Done.
In your Tasks database, add a new property and pick Button. Call it Done. Add an action, choose Edit and then This page, set Status to Done, and save.
That is the whole thing. Click it on any task and the status changes.
Level 2: Add a condition

Now the button only works when you want it to.
In my Books database I want the finished date to fill in, but only when the status is actually Finished. Not before.
Add a Button property called Finished. Add the condition Status is Finished. Then add the action, Edit and This page, and set End Date to Date triggered.
If the status is not Finished and you click it, nothing happens. Change the status, click again, and today's date appears.
Use Time triggered instead if you need the exact time, which matters for anything tracking durations.
Level 3: A formula inside the property

Here is where it starts being useful.
In my Punishments database, every punishment I owe gets paid off by clicking Done, which adds one to my done count. But once I do not owe anything, clicking should do nothing. The count should stop.
Make a Button called Done, action Edit then This page, and point it at the Done Count property. Switch that to a custom formula.
The obvious version looks like this.
This page.Done Count + 1
And it works, right up until you owe nothing and it keeps counting anyway. So you add the condition inside the formula.
if(This page.Debt > 0, This page.Done Count + 1, This page.Done Count)
If there is debt, add one. If not, write the same number back, so clicking changes nothing.
I tested this on my own strict challenge for processed sugar. I was on day 22, slipped back to day one, and owed a debt of one. Clicked the button, paid it, 300 push-ups done. Clicked again and nothing moved.
Level 4: Variables

That same Done button also stamps a Last Paid date. Which means it is checking the same condition twice, once for the count and once for the date. Write that condition out twice and you have two places to break it later.
So you define it once.
Add Define variables as the first action on the button. Make a variable called owes.
This page.Debt > 0
Then Edit and This page, and both properties just read that variable.
Done Count:
if(owes, This page.Done Count + 1, This page.Done Count)
Last Paid:
if(owes, now(), This page.Last Paid)
One rule, written once, reused in two properties.
This is the level that matters most, because everything from here on needs variables. Level five and six do not work without them.
Level 5: Edit a different page

Until now the button has only edited the page it sits on. It does not have to.
In my Weekly Report I attach a reward to the week. This week's is going out with the family. And I can only claim it if three things are true at once: I earned it by hitting more than 50% of my week's actions, the week is actually over, and I have enough coins to pay for it.
The button lives on the week. The checkbox it ticks lives on the reward.
Start with Define variables. First one is Reward, the reward linked to this week.
This page.Reward
⚠️ A thing that will catch you out. Variables in the same Define block cannot read each other. If you need one variable to use another, the second one goes in its own separate Define variables block. I hit this live and it is not obvious at all.
So in a second block, Enough Coins, which reaches into my character to check my coins against the reward's cost.
This page.Character.map(current.All time Coins).sum() >= This page.Reward.first().Cost
Then End Week.
This page.End Date <= today()
Now add the action, Edit, and here is the part people miss: pick Reward as the target, not This page. The variable shows up in the data source list as a page you can edit.
Set Reward Claimed to:
if(This page.Reward.first().Earned and Enough Coins and End Week, true, This page.Reward.first().Reward Claimed)
If all three are true, tick it. Otherwise write back whatever it already was, so nothing changes.
Earned there is a formula living in the Reward database itself. The button just reads it through the relation, which is worth knowing because it means your buttons and your formulas can share work rather than duplicating it.
Level 6: Use buttons instead of formulas
This is the one. This is why I made the video.
When I built Game Mode V3 inside my second brain, it was slow. Properly slow.
Take one token as an example, the comet. You earn it by going to your Battle Log every day and claiming it. Which means that page gets created around 300 times a year.
So my character had to walk every single one of those pages, check whether I had collected that day, then count how many comets I had earned, and the amount is different every day because it comes from a complex formula. Then it had to handle spending, because comets go out to challenges, to the exchange, to my companion. All of it in one formula.
Eleven seconds to load.
And that is one token. I also have XP, coins, keys, skills.
The fix
Instead of making the character count everything every time, I moved the counting into the button.
Now when I click claim, the button checks whether I am allowed to earn it, works out the amount once, and writes it into a plain number property on the character. The character does not calculate anything any more. It just reads a number.
That is the whole trick, and here is why it works: plain number properties do not slow Notion down. Complex formulas with map, filter and chains of relations do.
The calculation still happens. It just happens once, on a click, instead of every time the page loads.
The claim button


Define variables first. AddXP works out how much XP to give, and returns 0 if I already claimed today, if there is no date, or if the log is not from today.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.XP), 0)))
AddComet is the same checks for the comet. No XP means no comet.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.Comet), 0)))
Then I need what the character currently holds. CurXP and CurComet.
let(c, This page.Grind Pulse.first().Character.first().Battle XP, if(empty(c), 0, c))
let(c, This page.Grind Pulse.first().Character.first().Battle Comet, if(empty(c), 0, c))
Notice that chain. My Battle Log is not related to my character directly, so it goes through Grind Pulse to get there. Three relations deep. In a formula that would be painfully slow. In a button it runs once and it is fine.
And char, the character page itself.
This page.Grind Pulse.first().Character
Then Edit the char variable, and the two properties are just addition.
Battle Comet = AddComet + CurComet Battle XP = AddXP + CurXP
Finally Edit This page to lock it, so a second click pays nothing.
Points Claimed = if(empty(This page.Date), false, formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"))
⚠️ The order matters. Variables, then pay the character, then lock the page. Every variable is calculated before any edit runs, so locking last never breaks the payment, and clicking twice pays zero.
I use this same pattern everywhere now. Collect tokens on tasks, on books, on reviews. You cannot claim anything twice.
It was an overnight solution to a problem I had been living with for months, and I have never appreciated buttons the way I did that day.
Why buttons are underrated
Most people stop at level one. A button that ticks a box.
But once you understand that a button can carry conditions, hold variables, reach across relations and write to other pages, it stops being a shortcut and becomes somewhere you can move work to. And if your Notion system is slow, that is usually the fix. Not fewer pages. Less being recalculated every time you open something.
Learn them properly and you will build things you did not think Notion could do.
Every button in this article is from SB7 x Game Mode V3, the system I use to stay disciplined and turn my life into an RPG. It is also the system that taught me all of this, because it broke first.

→ Get SB7
Six levels, from a Done button to replacing your formulas

Database buttons made my Notion system about ten times faster, and I know how that sounds. What does a button have to do with a page loading?
I will get to that at level six, because it is the whole reason I made this. But I want to build up to it properly, so if you are new to buttons you can follow along from zero.
Six levels. The first three are easy, so if you already use buttons a lot, skip ahead to five and six. That is where it gets interesting.
Level 1: Edit this page

The simplest thing a button can do. One click moves a task from To Do to Done.
In your Tasks database, add a new property and pick Button. Call it Done. Add an action, choose Edit and then This page, set Status to Done, and save.
That is the whole thing. Click it on any task and the status changes.
Level 2: Add a condition

Now the button only works when you want it to.
In my Books database I want the finished date to fill in, but only when the status is actually Finished. Not before.
Add a Button property called Finished. Add the condition Status is Finished. Then add the action, Edit and This page, and set End Date to Date triggered.
If the status is not Finished and you click it, nothing happens. Change the status, click again, and today's date appears.
Use Time triggered instead if you need the exact time, which matters for anything tracking durations.
Level 3: A formula inside the property

Here is where it starts being useful.
In my Punishments database, every punishment I owe gets paid off by clicking Done, which adds one to my done count. But once I do not owe anything, clicking should do nothing. The count should stop.
Make a Button called Done, action Edit then This page, and point it at the Done Count property. Switch that to a custom formula.
The obvious version looks like this.
This page.Done Count + 1
And it works, right up until you owe nothing and it keeps counting anyway. So you add the condition inside the formula.
if(This page.Debt > 0, This page.Done Count + 1, This page.Done Count)
If there is debt, add one. If not, write the same number back, so clicking changes nothing.
I tested this on my own strict challenge for processed sugar. I was on day 22, slipped back to day one, and owed a debt of one. Clicked the button, paid it, 300 push-ups done. Clicked again and nothing moved.
Level 4: Variables

That same Done button also stamps a Last Paid date. Which means it is checking the same condition twice, once for the count and once for the date. Write that condition out twice and you have two places to break it later.
So you define it once.
Add Define variables as the first action on the button. Make a variable called owes.
This page.Debt > 0
Then Edit and This page, and both properties just read that variable.
Done Count:
if(owes, This page.Done Count + 1, This page.Done Count)
Last Paid:
if(owes, now(), This page.Last Paid)
One rule, written once, reused in two properties.
This is the level that matters most, because everything from here on needs variables. Level five and six do not work without them.
Level 5: Edit a different page

Until now the button has only edited the page it sits on. It does not have to.
In my Weekly Report I attach a reward to the week. This week's is going out with the family. And I can only claim it if three things are true at once: I earned it by hitting more than 50% of my week's actions, the week is actually over, and I have enough coins to pay for it.
The button lives on the week. The checkbox it ticks lives on the reward.
Start with Define variables. First one is Reward, the reward linked to this week.
This page.Reward
⚠️ A thing that will catch you out. Variables in the same Define block cannot read each other. If you need one variable to use another, the second one goes in its own separate Define variables block. I hit this live and it is not obvious at all.
So in a second block, Enough Coins, which reaches into my character to check my coins against the reward's cost.
This page.Character.map(current.All time Coins).sum() >= This page.Reward.first().Cost
Then End Week.
This page.End Date <= today()
Now add the action, Edit, and here is the part people miss: pick Reward as the target, not This page. The variable shows up in the data source list as a page you can edit.
Set Reward Claimed to:
if(This page.Reward.first().Earned and Enough Coins and End Week, true, This page.Reward.first().Reward Claimed)
If all three are true, tick it. Otherwise write back whatever it already was, so nothing changes.
Earned there is a formula living in the Reward database itself. The button just reads it through the relation, which is worth knowing because it means your buttons and your formulas can share work rather than duplicating it.
Level 6: Use buttons instead of formulas
This is the one. This is why I made the video.
When I built Game Mode V3 inside my second brain, it was slow. Properly slow.
Take one token as an example, the comet. You earn it by going to your Battle Log every day and claiming it. Which means that page gets created around 300 times a year.
So my character had to walk every single one of those pages, check whether I had collected that day, then count how many comets I had earned, and the amount is different every day because it comes from a complex formula. Then it had to handle spending, because comets go out to challenges, to the exchange, to my companion. All of it in one formula.
Eleven seconds to load.
And that is one token. I also have XP, coins, keys, skills.
The fix
Instead of making the character count everything every time, I moved the counting into the button.
Now when I click claim, the button checks whether I am allowed to earn it, works out the amount once, and writes it into a plain number property on the character. The character does not calculate anything any more. It just reads a number.
That is the whole trick, and here is why it works: plain number properties do not slow Notion down. Complex formulas with map, filter and chains of relations do.
The calculation still happens. It just happens once, on a click, instead of every time the page loads.
The claim button


Define variables first. AddXP works out how much XP to give, and returns 0 if I already claimed today, if there is no date, or if the log is not from today.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.XP), 0)))
AddComet is the same checks for the comet. No XP means no comet.
if(This page.Points Claimed, 0, if(empty(This page.Date), 0, if(formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"), if(empty(This page.XP), 0, This page.Comet), 0)))
Then I need what the character currently holds. CurXP and CurComet.
let(c, This page.Grind Pulse.first().Character.first().Battle XP, if(empty(c), 0, c))
let(c, This page.Grind Pulse.first().Character.first().Battle Comet, if(empty(c), 0, c))
Notice that chain. My Battle Log is not related to my character directly, so it goes through Grind Pulse to get there. Three relations deep. In a formula that would be painfully slow. In a button it runs once and it is fine.
And char, the character page itself.
This page.Grind Pulse.first().Character
Then Edit the char variable, and the two properties are just addition.
Battle Comet = AddComet + CurComet Battle XP = AddXP + CurXP
Finally Edit This page to lock it, so a second click pays nothing.
Points Claimed = if(empty(This page.Date), false, formatDate(This page.Date, "MMMM D, Y") == formatDate(now(), "MMMM D, Y"))
⚠️ The order matters. Variables, then pay the character, then lock the page. Every variable is calculated before any edit runs, so locking last never breaks the payment, and clicking twice pays zero.
I use this same pattern everywhere now. Collect tokens on tasks, on books, on reviews. You cannot claim anything twice.
It was an overnight solution to a problem I had been living with for months, and I have never appreciated buttons the way I did that day.
Why buttons are underrated
Most people stop at level one. A button that ticks a box.
But once you understand that a button can carry conditions, hold variables, reach across relations and write to other pages, it stops being a shortcut and becomes somewhere you can move work to. And if your Notion system is slow, that is usually the fix. Not fewer pages. Less being recalculated every time you open something.
Learn them properly and you will build things you did not think Notion could do.
Every button in this article is from SB7 x Game Mode V3, the system I use to stay disciplined and turn my life into an RPG. It is also the system that taught me all of this, because it broke first.







