sf-visualforce-development
Skill15 starsChanged 7 months agoMITView on GitHub
Visualforce development — pages, controllers, extensions, ViewState, JS Remoting, LWC migration. Use when maintaining VF pages, building PDFs, or planning VF-to-LWC migration. Do NOT use for LWC, Aura, or Flow.
In this repository58 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- asideSkill
- checkpointSkill
- configure-sccSkill
- continuous-agent-loopSkill
- mcp-server-patternsSkill
- model-routeSkill
- prompt-optimizerSkill
- refactor-cleanSkill
- resume-sessionSkill
- save-sessionSkill
- search-firstSkill
- security-scanSkill
- sessionsSkill
- sf-2gp-security-reviewSkill
- sf-agentforce-developmentSkill
- sf-agentforce-mcp-actionsSkill
- sf-apex-async-patternsSkill
- sf-apex-best-practicesSkill
- sf-apex-constraintsSkill
- sf-apex-cursorSkill
- sf-apex-enterprise-patternsSkill
- sf-apex-testingSkill
- sf-api-designSkill
- sf-approval-processesSkill
- sf-aura-developmentSkill
- sf-build-fixSkill
- sf-cli-referenceSkill
- sf-data-modelingSkill
- sf-debuggingSkill
- sf-deployment-constraintsSkill
- sf-deploymentSkill
- sf-devops-ci-cdSkill
- sf-docs-lookupSkill
- sf-e2e-testingSkill
- sf-experience-cloudSkill
- sf-flow-developmentSkill
- sf-governor-limitsSkill
- sf-harness-auditSkill
- sf-helpSkill
- sf-integrationSkill
- sf-lwc-constraintsSkill
- sf-lwc-developmentSkill
- sf-lwc-testingSkill
- sf-metadata-managementSkill
- sf-platform-events-cdcSkill
- sf-quickstartSkill
- sf-security-constraintsSkill
- sf-securitySkill
- sf-soql-constraintsSkill
- sf-soql-optimizationSkill
- sf-tdd-workflowSkill
- sf-testing-constraintsSkill
- sf-trigger-constraintsSkill
- sf-trigger-frameworksSkill
- strategic-compactSkill
- update-docsSkill
- update-platform-docsSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 5 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
When maintaining or extending existing Visualforce pages in production
- Very specific: line 14
When building PDF renderable pages (renderAs="pdf") — LWC cannot do this
- Distinctive: line 15
When creating custom email templates with complex formatting
- Distinctive: line 16
When overriding standard buttons (New, Edit, View) with custom UIs
- Distinctive: line 17
When planning and executing migration from Visualforce to LWC
- Distinctive: line 18
When debugging ViewState issues or page performance problems
- Very specific: line 178
Use {!$RemoteAction.ClassName.methodName} (namespace-safe).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Visualforce Development
Visualforce is Salesforce's server-side rendering framework. While LWC is the modern standard, Visualforce remains heavily used for PDF generation, email templates, custom overrides, and legacy applications.
When to Use
- When maintaining or extending existing Visualforce pages in production
- When building PDF renderable pages (
renderAs="pdf") — LWC cannot do this - When creating custom email templates with complex formatting
- When overriding standard buttons (New, Edit, View) with custom UIs
- When planning and executing migration from Visualforce to LWC
- When debugging ViewState issues or page performance problems
@../_reference/VISUALFORCE_PATTERNS.md
Page Creation Procedure
Step 1 — Choose Controller Type
| Type | When to Use |
| Standard Controller | Single-record CRUD without custom logic |
| Standard List Controller | List views with built-in pagination |
| Custom Controller | Full control over logic, data, navigation |
| Controller Extension | Add functionality to standard/custom controllers |
Step 2 — Create the Page
<apex:page standardController="Account"
extensions="AccountOverviewExtension"
lightningStylesheets="true"
docType="html-5.0"
title="Account Overview">
<apex:pageBlock title="Account Details">
<apex:pageBlockSection columns="2">
<apex:outputField value="{!Account.Name}" />
<apex:outputField value="{!Account.Industry}" />
</apex:pageBlockSection>
</apex:pageBlock>
</apex:page>Step 3 — Custom Controller (if needed)
public with sharing class InvoiceController {
public List<Invoice__c> invoices { get; private set; }
public String searchTerm { get; set; }
public InvoiceController() {
searchTerm = '';
loadInvoices();
}
public PageReference search() {
loadInvoices();
return null; // Stay on same page
}
private void loadInvoices() {
String likeSearch = '%' + String.escapeSingleQuotes(searchTerm) + '%';
invoices = [
SELECT Id, Name, Amount__c, Status__c, CreatedDate
FROM Invoice__c WHERE Name LIKE :likeSearch
WITH USER_MODE ORDER BY CreatedDate DESC LIMIT 100
];
}
}Step 4 — Controller Extension (if needed)
public with sharing class AccountOverviewExtension {
private final Account account;
// Required constructor signature
public AccountOverviewExtension(ApexPages.StandardController stdController) {
if (!Test.isRunningTest()) {
stdController.addFields(new List<String>{ 'OwnerId', 'AnnualRevenue' });
}
this.account = (Account) stdController.getRecord();
}
public List<Contact> relatedContacts {
get {
if (relatedContacts == null) {
relatedContacts = [
SELECT Id, Name, Email, Phone
FROM Contact WHERE AccountId = :account.Id
WITH USER_MODE ORDER BY Name LIMIT 50
];
}
return relatedContacts;
}
private set;
}
}ViewState Management
ViewState is a hidden, encrypted form field that maintains page state across postbacks. 170KB limit — exceeding it causes a runtime error.
The transient Keyword
Mark variables that do not need to survive postbacks as transient:
public with sharing class ReportController {
// IN ViewState — needed across postbacks
public String selectedFilter { get; set; }
public Integer currentPage { get; set; }
// NOT in ViewState — recomputed on each request
transient public List<AggregateResult> reportData { get; private set; }
transient public Blob chartImage { get; private set; }
}Reduction Strategies
| Strategy | Impact |
transient keyword on large/recomputable variables | High |
apex:outputPanel + reRender (partial refresh) | Medium |
| Paginate large data sets | High |
| Use JavaScript Remoting (stateless) | High |
Move read-only data outside apex:form | Medium |
JavaScript Remoting
Stateless, high-performance Apex calls that bypass ViewState entirely.
Apex Method
@RemoteAction
public static List<Account> findAccounts(String searchTerm) {
String safeTerm = '%' + String.escapeSingleQuotes(searchTerm) + '%';
return [
SELECT Id, Name, Industry FROM Account
WHERE Name LIKE :safeTerm WITH USER_MODE LIMIT 25
];
}JavaScript Invocation
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.AccountSearchController.findAccounts}',
term,
function(result, event) {
if (event.status) {
renderResults(result);
} else {
console.error(event.message);
}
},
{ escape: true, timeout: 30000 }
);Use {!$RemoteAction.ClassName.methodName} (namespace-safe). Set escape: true to prevent XSS.
Partial Page Refresh
<apex:actionFunction name="refreshDashboard" action="{!refresh}"
reRender="dashPanel" status="loadingStatus" />
<apex:selectList value="{!selectedRegion}" size="1">
<apex:selectOptions value="{!regionOptions}" />
<apex:actionSupport event="onchange" action="{!filterByRegion}"
reRender="dashPanel" status="loadingStatus" />
</apex:selectList>
<apex:actionStatus id="loadingStatus">
<apex:facet name="start"><img src="/img/loading.gif" alt="Loading..." /></apex:facet>
</apex:actionStatus>Migration to LWC
Decision Matrix
| Keep Visualforce | Migrate to LWC |
PDF generation (renderAs="pdf") | High-traffic pages needing performance |
| Email templates | New feature development |
| Complex server-state wizards | Pages using Apex controller only |
Key VF-to-LWC Mappings
| Visualforce | LWC |
apex:pageBlockTable | lightning-datatable |
apex:commandButton action="{!save}" | lightning-button onclick={handleSave} + imperative Apex |
apex:inputField | lightning-input-field (in lightning-record-edit-form) |
| JavaScript Remoting | @wire or imperative Apex import |
apex:actionSupport | Standard DOM event handlers |
{!property} merge fields | {property} template expressions |
Embedding LWC in Visualforce (Lightning Out)
For incremental migration, embed LWC inside existing VF pages:
<apex:includeLightning />
<div id="lwc-container"></div>
<script>
$Lightning.use("c:lwcOutApp", function() {
$Lightning.createComponent("c:accountDashboard",
{ recordId: "{!Account.Id}" }, "lwc-container");
});
</script>Migration Checklist
- Inventory — list all VF pages, controllers, usage frequency
- Categorize — mark each page as Keep VF / Migrate / Retire
- Dependencies — map controller extensions, custom components, static resources
- Security audit — review XSS/injection issues before or during migration
- Feature parity — replicate all VF functionality in LWC
- Test coverage — write LWC Jest tests to match existing Apex test coverage
- Incremental rollout — use Lightning Out to embed LWC in VF during transition
- Redirect — update links, overrides, navigation to new LWC pages
- Deprecate — mark old VF pages as inactive, remove after validation
Related
Guardrails
- sf-security-constraints — Enforced rules for XSS prevention, SOQL injection, CRUD/FLS enforcement
Agents
- sf-visualforce-reviewer — For interactive, in-depth Visualforce review guidance
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

