Skip to main content

AMA Custom Blocks Contest Edition #2 - Prototyping and Polishing with the Airtable Design Team


Show first post

38 replies

Forum|alt.badge.img+13
kuovonne wrote:

Could you expand a bit more on local storage? Is it unique to the specific user and block? Can it be accessed outside the block? Is it suitable for storing sensitive information such as API keys or passwords? Does it persist after the block is closed? Does it persist after Airtable is closed? Does it persist after the computer is restarted?


I haven’t worked with local storage extensively, but I believe the answers would be yes, yes, and no.

An example use case I’m trying to think of is one where multiple users want to use the block, calling an external service with their own API keys (so as to keep requests and data manipulation tied to a specific user and not the “global” API key stored in a config). Local storage would solve this problem to make it per-individual, but being wiped on restart is less than ideal.

The cache might only be wiped manually though (clear browser data) instead of on computer restart, but I’m not sure. Definitely something I’ll be looking into!


Forum|alt.badge.img+19
kuovonne wrote:

Could you expand a bit more on local storage? Is it unique to the specific user and block? Can it be accessed outside the block? Is it suitable for storing sensitive information such as API keys or passwords? Does it persist after the block is closed? Does it persist after Airtable is closed? Does it persist after the computer is restarted?


Could you expand a bit more on local storage? Is it unique to the specific user and block? Can it be accessed outside the block? Is it suitable for storing sensitive information such as API keys or passwords? Does it persist after the block is closed? Does it persist after Airtable is closed? Does it persist after the computer is restarted?

You can read more information about the local storage API here: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

In short, it’s unique to a specific browser for a specific block installation. It cannot be accessed outside the block. It is persisted between sessions unless the user explicitly clears their browser’s local storage. You could store sensitive information there, but it would be accessible by anyone who has physical access to that machine. Also note that anything in local storage won’t be shared between different users of the block (e.g. each user of the block would need to input their own API key).


Kamille_Parks11
Forum|alt.badge.img+25

Has airtable considered offering a way to color a Record using a custom logic that is separate from a View’s or Select Field’s coloring settings?

It would be nice to have a 4th, custom Record Color Mode (Airtable Blocks SDK) where we can just feed a record/list of records a hex value or a standard color.util value.


Forum|alt.badge.img+19
Matthew_Thomas wrote:

I haven’t worked with local storage extensively, but I believe the answers would be yes, yes, and no.

An example use case I’m trying to think of is one where multiple users want to use the block, calling an external service with their own API keys (so as to keep requests and data manipulation tied to a specific user and not the “global” API key stored in a config). Local storage would solve this problem to make it per-individual, but being wiped on restart is less than ideal.

The cache might only be wiped manually though (clear browser data) instead of on computer restart, but I’m not sure. Definitely something I’ll be looking into!


The cache might only be wiped manually though (clear browser data) instead of on computer restart.

This is correct, local storage is not wiped on restart.


Forum|alt.badge.img+13
Stephen_Suen wrote:

The cache might only be wiped manually though (clear browser data) instead of on computer restart.

This is correct, local storage is not wiped on restart.


Fantastic! Didn’t have to look far :laughing:


Forum|alt.badge.img+19
kuovonne wrote:

What will happen to questions in this thread that aren’t answered before time runs out?


What will happen to questions in this thread that aren’t answered before time runs out?

No worries — we’ll answer any questions that were posted in this thread before 11:30 AM PT.


  • Participating Frequently
  • 6 replies
  • June 17, 2020
kuovonne wrote:

Can you tell us a little more about the decision to host this contest on devpost.com versus how you hosted the contests for scripting block?

Is it possible to submit one block as part of a team, and another block as a solo entry? How would one go about that?

If I have a set of blocks that are meant to be used together in a workflow, would that be two separate entries? Or would they each be independent entries? Each block would have its own repository, and each block could be used independently. However the value of the two blocks is enhanced when they are used in conjunction with each other.

If I use a module from npm with an “MIT” license, is that fair game for the contest? Do I need to do anything for the purposes of the contest to document that I use the module? The module won’t appear in the git repository by default. By default, it will simply be listed in package.json. Is that enough?


Hi Kuovonne, thanks for you question!

Can you tell us a little more about the decision to host this contest on devpost.com versus how you hosted the contests for scripting block?

The Custom Blocks Contest is on a much larger scale than the scripting block contest. Devpost helps us with contest management complexities like prize fulfilment.

Is it possible to submit one block as part of a team, and another block as a solo entry? How would one go about that?

Yes, you can submit one block as part of a team, and another block as a solo entry.

To submit multiple blocks, you would just need to create a second submission/ project. You can create a new project page through their portfolio, using the “Add a new project” button, located under your profile picture.

After you fill in all the basic information and save, you would see a prompt asking if you want to submit the project to a hackathon:

Select yes, then scroll through the list and click on the correct hackathon name.

If you’re still having trouble figuring out how to do that, you can email support@devpost.com.

If I have a set of blocks that are meant to be used together in a workflow, would that be two separate entries? Or would they each be independent entries? Each block would have its own repository, and each block could be used independently. However the value of the two blocks is enhanced when they are used in conjunction with each other.

Blocks are designed to work better together, so it’s perceptive that you’ve noticed this opportunity while building blocks! Since the blocks work independently, I would suggest you submit them as separate entries. We expect blocks to enhance each other anyways.

If I use a module from npm with an “MIT” license, is that fair game for the contest? Do I need to do anything for the purposes of the contest to document that I use the module? The module won’t appear in the git repository by default. By default, it will simply be listed in package.json. Is that enough?

To your question about using a package with a MIT license: yes, you can use open source packages in the contest as long as you are using it in accordance with the license. You can refer to our contest rules if you have any further queries!


Forum|alt.badge.img+19
kuovonne wrote:

For the purposes of the contest, can a block submitted to the contest use the button beta, or do entries need to use only released features (other than custom blocks itself)?

For example, I wrote a block that is invoked by a button field (thanks Kamille!), because I prefer that workflow. If I want to submit my block for the contest, should I re-write it to have a different method of launching?


Yes, it’s fine for your submission to use the button beta. However, the block should not rely on the existence of a button field and there should be an alternative way to launch the block. As an example, you can run the scripting block from a button field but you can also run it directly from within the block.


Forum|alt.badge.img+19
Matthew_Thomas wrote:

Kind of building off of a part of @kuovonne’s latest question

I’ve written some Custom Block-specific helper functions to do some common operations like batch operations. These live in a helpers.js file in the same directory as my custom block. If however, I have an idea for how multiple blocks can operate together, moving the helpers.js file to a common parent directory the blocks will not find the code. Say I have a parent blocks directory, inside of which I have block_1 and block_2 directories with the code for my two custom blocks. Importing the helper file (two dirs up in the tree, hence ../../) results in an error message like the following:

Updating bundle...
Bundle Error: Cannot find module '../../helpers' from '~/blocks/block_1/build/development/transpiled/user/frontend'

Is/will importing local modules be supported by custom blocks? Would it make more sense to package-ify my helper files, or is there another solution so I don’t have to copy/paste the file to each block after I make changes?


This is something the team is thinking about, but in the meantime, your best bets are the options you called out — either copy-paste the code between your blocks or host the shared code online e.g. in a GitHub repository or npm package.


Forum|alt.badge.img+19
Kamille_Parks11 wrote:

For that error, make sure you are only trying to run the custom block from the Base you originally set it up in, and on the same computer.


You must run the block in the base it was created in, but you can run it on a different computer as long as it has the same .block/remote.json file (it should contain the block id and base id).


Forum|alt.badge.img+19
kuovonne wrote:

I noticed that the Blocks API Reference has multiple functions for permission checks. In particular, I noticed that there are different permission checks for operations on a single record versus batch operations for multiple records.

Is this an indication that you are looking into more granular permissions for batch operations in Airtable? Would these permissions for batch operations also apply to the Scripting API, the Standard REST API, and native UI?

Also, what do you think of having permissions that allow changes (create, delete, update) only through code (scripting block or custom blocks)? In this use case, a low-level user could still create, delete, and update data when using a custom block that enforces business logic, but wouldn’t be able to make changes to data directly that doesn’t have any code protecting business logic.


The intent of these APIs was to have a corresponding permissions check method for each mutation method. We’d love to hear about what you’d be trying to accomplish with granular permissions for batch operations.

Yes, this is something we’re thinking about — more to come later on this.


  • Participating Frequently
  • 6 replies
  • June 17, 2020
Kirill_Madorin wrote:

Hello Airtable team!

Could you answer these questions?

  1. I’m trying to implement image an Image annotation block from the list of possible use cases. Screenshot 2020-06-16 at 22.50.27|700x389

Could you suggest any ideas on how to implement this layout? I’ve managed to do it only by setting the fixed height for the wrapper block for now. Otherwise a scroll appears because of the overflow:auto property on body element in the iframe. Current code is here:

<Box width={'100%'} height={362} display='flex'>
	<Box width={'70%'} height={'100%'} display={"flex"} flexDirection={"column"} justifyContent={"stretch"}>
		<Box overflow={'auto'} border={'1px solid red'} flexGrow={1}>
			<Text size={"xlarge"}>Big images are possible here. This block should be with overflow: auto</Text>
			{/*<ImageFromRecord*/}
		    {/*	activeTable={activeTable} selectedRecordId={selectedRecordId} selectedFieldId={selectedFieldId}*/}
		    {/*	annotations={getAnnotationsShapes()}*/}
		    {/*	onAnnotationAdding={handleAnnotationAdding}*/}
		    {/*/>*/}
		</Box>
		<Box border={'1px solid blue'}>
			<Text size={"xlarge"}>Annotation form here.</Text>
			{/*<AnnotationForm onSubmit={handleAnnotationSubmit} onChange={handleAnnotationFormChange}/>*/}
		</Box>
	</Box>
	<Box as={'aside'} width={'30%'} border={'1px solid green'}>
		<Text size={"xlarge"}>List of annotations here</Text>
		{/*<AnnotationsList annotations={annotations}/>*/}
	</Box>
</Box>

I can set height for the wrapper based on window.innerHeight and add change it on resize. But maybe you can give me an advice on better solution?

  1. The second question is about UX. Does it make sense to make the image annotation block available only in FullScreen mode?

Hi Kirill, thanks for your question.

  1. I’m trying to implement image an Image annotation block from the list of possible use cases. Screenshot 2020-06-16 at 22.50.27|700x389

Could you suggest any ideas on how to implement this layout? I’ve managed to do it only by setting the fixed height for the wrapper block for now. Otherwise a scroll appears because of the overflow:auto property on body element in the iframe.

I can set height for the wrapper based on window.innerHeight and add change it on resize. But maybe you can give me an advice on better solution?

I believe what you want is for the wrapper box to be position="absolute" and have left/top/right/bottom properties set to 0, here is an example:

<Box position="absolute" top={0} bottom={0} left={0} right={0} display="flex">{...}</Box>

The panels within will have to be constructed with the right flex child properties and to achieve scrolling/overflow you will add overflow="auto" on the desired box.

  1. The second question is about UX. Does it make sense to make the image annotation block available only in FullScreen mode?

Good question, in general we like to think more about the size of the block instead of fullscreen or not. We have some utilities to enforce a min size of the block through the ViewportConstraint component. You would end up with something like the following,

<ViewportConstraint minSize={{width: 400, height: 400}}>
   {...}
</ViewportConstraint>

Forum|alt.badge.img+19

Thank you to everyone for participating in today’s AMA. As always, feel free to leave any additional questions you have in the Custom Blocks Beta forum.

We’ll be awarding gift cards to @Kamille_Parks, @Matthew_Thomas, and @kuovonne. Look out for another AMA same time next week!


Reply