
Components are pieces of HTML, CSS, and JS that can be added to posts or other components. They allow for customization by giving users custom fields to input data into. This post will discuss all parts of a component.
The title is required, and must be 4 to 20 characters long.
The description is required, and must be 20 to 255 characters. It appears in searches, so it should describe the purpose it serves, and any benefits and limits to using it. For instance, if you were creating a bar graph, it would be useful to mention if it allows for certain customizations such as colors of the bars, and if there is a limit on the number of bars that may be added.
The details section is optional. It displays after a component has been selected, and above the data that is requested from the user. Relevant info about how the component works, and customization options go here. Continuing with the bar graph example, you could write that if a bar color is not specified, blue is used, and that for customization, the bars have the class 'bar' that may be edited by adding a <style> element to their post.
Line breaks are conserved in details, so you can separate topics into different parts.
User-Entered Data is also optional. When used, each field in the row is required.
All user-entered data becomes a part of an object for your code. Each component has a unique id, and this id is embedded into the source variable name of this user-entered data object. If the component's id is iOK0H, the source variable for your component is dataiOK0H (will be used as an example throughout this doc). This is still the variable name you should use in your code when accessing component data.
Each component also has a config object named dataiOK0H_config. It includes created, previewHtml, componentId, and localId. On the full post page it also includes fragment, which is the current url fragment without the leading #.
Store Data
We allow saving data per user via the store data field. To update the store data field for a user, see the "Global Functions" -> "Store Data" section. You can edit the rules and keys for a store data field by clicking the "Edit Fields and Rules" button. The data is provided to a component in this format (if component id is iOK0H and property name is pollValues):
dataiOK0H['pollValues'] = {
"userInput": {
"poll_question": [null,1],
"poll_user_count": 1
},
"userInputMeta": {
"created": "2026-07-07 05:52:00",
"modified":"2026-07-07 05:52:00"
},
"aggregateValues": {
"poll_question": [null,1],
"poll_user_count": 1
}
};userInputMeta's date and time properties are when the userInput values were saved for this user. They are in UTC. If no values have been supplied for this user, it will look like:
dataiOK0H['pollValues'] = {
"userInput": {
"poll_question": [],
"poll_user_count": null
},
"userInputMeta": {
created: null,
modified: null
},
"aggregateValues": {
"poll_question": [],
"poll_user_count": null
}
};
To allow for multiple instances of your component to be added to one post, every instance of dataiOK0H is still rewritten before your code runs so that each instance gets its own runtime variable. Use dataiOK0H in your source code so the system can rewrite it correctly.
When a component is added to a post, it is given a localId (starts at 0 and auto-increments). This localId is visible in the code editor, so the user can use it if necessary (described later). If your component is the third added, it will have a localId of 2. Before your code is run, instances of dataiOK0H are rewritten to a runtime-specific variable that includes the localId, and it may also include an added random string. Because of that, do not depend on the final rewritten variable name being stable across renders.
If you need stable values for ids, class names, fragment targets, or other generated markup, use dataiOK0H_config.componentId and dataiOK0H_config.localId.
You can let users custom style your components by mentioning class names and ids in the Detail section of the component page. If you want those selectors to stay stable, build them from dataiOK0H_config.componentId and dataiOK0H_config.localId instead of depending on the final rewritten runtime variable name. So if your class is based on those stable config values, users can target it reliably without worrying about runtime rewriting.
When a component is rendered, the site also exposes a runtime config object. This gives your component a few useful values about the current render context, like the component instance id and the current max render height.
Example:
window.dataAB12_config = {
created: 1713990000000,
previewHtml: "<p>Example post content</p>",
fragment: "",
maxHeight: 300,
componentId: "AB12",
localId: "0",
};Store Data
If you choose the Store Data field type, that field must be at the top level. Store Data lets a component load saved values for the current user and aggregate values returned by the backend. The configured keys for that field become data properties, and those keys may only contain letters, numbers, and underscores.
At runtime, call window.fgStoreData. It return a Promise. On success, the requested property on your component data object is updated with an object containing userInput and aggregateValues. In this case, scores is the "Data Property Name" value for this Store Data field in the User-Entered Data.
window.fgStoreData('load', 'dataiOK0H', 'scores').then(function () {
console.log(dataiOK0H.scores.userInput);
console.log(dataiOK0H.scores.aggregateValues);
});To save data, call window.fgStoreData with an additional parameter, which must be an object with a userInput property. The properties allowed on the userInput are set for the field by clicking the "Edit Fields and Rules" button, and adding to the Fields section. The Key for each field make up the exact properties we will allow.
window.fgStoreData('save', 'dataiOK0H', 'scores', {
userInput: {
score: 7
}
}).then(function () {
console.log(dataiOK0H.scores.userInput);
});Saving requires the user to be logged in. In previews, Store Data uses the configured test payload until the component is attached to a post.
window.fgStoreData returns a Promise and may reject if the request fails, the field cannot be identified, the supplied data is invalid, or a save is attempted while logged out. Components should handle these errors.
window.fgStoreData('save', 'dataiOK0H', 'scores', {
userInput: {
score: 7
}
}).then(function () {
console.log(dataiOK0H.scores.userInput);
}).catch(function (error) {
console.error(error.message);
});When a logged-out user attempts to save, the signup flow is opened and the Promise rejects. Loading does not require the user to be logged in.
Force Signup Flow
window.fgRequireSignup
This function triggers the signup modal flow. Use it when interacting with buttons that will later require data to be saved
Add Component to New Post
window.fgAddComponentToPost
This function opens the new post page and opens the Add Component modal with the calling component selected. Pass the component's config object so the correct component can be identified.
window.fgAddComponentToPost(dataiOK0H_config);
You may also pass the component id directly:
window.fgAddComponentToPost(dataiOK0H_config.componentId);
The function returns truefalsetrue
Unlike posts, components cannot be used or seen in search results until they are approved. This is to prevent malicious code from becoming widespread before being deleted, and potentially diminishing the UX for users visiting posts that had a component deleted retroactively. To ensure your component is approved, refrain from using external JS files that could be changed maliciously in the future. Only repositories on unpkg.com - like jQuery, React, and other npm packages - will be allowed. Aside from common social media, all other script urls are blocked by our Content-Security-Policy. If you have another site you'd like to include scripts from, please submit feedback (in the dropdown menu in the upper right hand corner when you log in).
Add the following to enable react:
<script src='https://unpkg.com/react/umd/react.production.min.js'></script> <script src='https://unpkg.com/react-dom/umd/react-dom.production.min.js'></script>
When testing, use the following:
<script src='https://unpkg.com/react/umd/react.development.js'></script> <script src='https://unpkg.com/react-dom/umd/react-dom.development.js'></script>
When a new version of a component is approved, changes will not automatically propagate to posts using that component. Posts will have to be updated individually. This was done because updated components may no longer fit in as well with the post, and can change user-entered data formatting.
Use dataiOK0H for your component's actual data. Use dataiOK0H_config.componentId and dataiOK0H_config.localId when you need stable html ids, class names, or fragment targets.
const sectionId = `${dataiOK0H_config.componentId}-${dataiOK0H_config.localId}-results`;On the full post page, dataiOK0H_config.fragment contains the current url fragment without the leading #. This can be used if your component needs to react to a specific fragment when the post is opened.
If you want a button or link inside a rendered component to open the full post and jump to a specific element, add data-click-bridge-fragment to the clicked element. The value should match the target element's id, with or without the leading #.
<button data-click-bridge-fragment='results-section'>View Results</button> <a href='#' data-click-bridge-fragment='results-section'>View Results</a>
The target element should use a stable id, ideally one built from dataiOK0H_config.componentId and dataiOK0H_config.localId. If you only want to open the post without adding a hash, use data-click-bridge-navigate.
Because pages are loaded two different ways, you must plan accordingly. If you need to wait for the page to load to examine or manipulate elements, you will have to check to see if the document has loaded already before adding a window load event listener:
// when using React componentDidMount() { if (document.readyState !== 'complete') { this.listenerSet = true; window.addEventListener('load', this.loadData); } else { this.listenerSet = false; this.loadData(); } }For removing the listener in React:
componentWillUnmount() { if (this.listenerSet) { window.removeEventListener('load', this.loadData); } }Without React:
if (document.readyState !== 'complete') { window.addEventListener('beforeunload', function (event) { window.removeEventListener('load', this.loadData); }); }
Enabling interactive authoring allows a component to replace the normal Add Component data form with a full-width interactive preview. The component can provide its own controls for updating User-Entered Data.
The optional Add Component Preview Code is appended to the component only while it is displayed in the Add Component preview. It can be used for controls and behavior needed during authoring but should not appear in the published component.
The interactive-authoring functions below return Promises. Although the global function names may exist in other render contexts, requests will reject unless interactive authoring is enabled and the component is currently running in an interactive Add Component preview.
Update User-Entered Data
window.fgUpdateUserData updates a User-Entered Data field. The resolved value is the value accepted after validation and sanitization.
window.fgUpdateUserData(
'dataiOK0H',
'heading',
'New heading'
).then(function (result) {
console.log(result.value);
}).catch(function (error) {
console.error(error.message);
});For a field inside a repeating collection, pass its collection index as the fourth argument.
window.fgUpdateUserData( 'dataiOK0H', 'heading', 'Second heading', 1 );
Pick an Image
window.fgPickUserDataImage opens the image picker for an image field. Image uploads require the user to be logged in. A collection index may be supplied as the third argument.
window.fgPickUserDataImage(
'dataiOK0H',
'image'
).then(function (result) {
console.log(result.value);
}).catch(function (error) {
console.error(error.message);
});
Change Collection Items
These functions add, remove, or reorder repetitions of a Collection field. Collection minimum and maximum limits are enforced. The data property must belong to the parent Collection field rather than one of its child fields.
window.fgAddCollectionItem('dataiOK0H', 'rows');
window.fgRemoveCollectionItem(
'dataiOK0H',
'rows',
1
);
window.fgReorderCollectionItem(
'dataiOK0H',
'rows',
0,
2
);Each collection function returns a Promise and rejects if the collection, index, or requested operation is invalid.
https://apnews.com/article/60c79349b60ffbf24a34d60b76e130ed
Major win for the Democrat's progressive wing in a state neither party can take for granted. El-Sayed now has to prove that primary enthusiasm can translate into a broader coalition against the republican in November.
I'm a bartender, and I see people come in stressed or fake smiling then leave after a few drinks and some bad decisions looking lighter.
Sitting in a quiet room talking about your childhood for an hour just keeps you stuck in your head. Go dance, talk shit with strangers, make dumb choices.
NOT saying never get help but most folks just need to get out of their apartment and stop treating every feeling like a crisis.
I'm hitting glutes 3x a week and ending up around 20 hard sets total. Mostly hip thrusts, RDLs, split squats and abductions.
Strength was moving up for a while but now Im just permanently sore and my last few sets feel kinda pointless. Sleep and protein are fine.
Would you cut sets first or just drop the third day entirely? Curious where everyone elses sweet spot is for actually growing
https://www.cbsnews.com/news/ice-detentions-trump-high-july-2026-immigration-crackdown-widens/
ICE detained more than 46k people in July and is now holding about 68k. 68k people in a concentration camp smh
I've watched it play out in warehouses Ive worked at. Hire or promote for the checklist instead of who can actually move freight without wrecking stuff or getting hurt. Then everyone acts shocked when quality tanks and people quit or get hurt. Merit used to mean something