Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactoring to move to app router #96

Merged
merged 12 commits into from
May 25, 2024
Merged

Conversation

thomasdavis
Copy link
Member

No description provided.

Copy link

vercel bot commented May 24, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
jsonresume-org-homepage2 ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 25, 2024 1:54am
jsonresume-org-registry ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 25, 2024 1:54am

Copy link

changeset-bot bot commented May 24, 2024

⚠️ No Changeset found

Latest commit: dd0d614

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented May 24, 2024

Walkthrough

The recent updates enhance the registry application with new error handling utilities, data formatters, and resume generation functions. The schema for resumes is defined, enabling fetching and formatting resume data from GitHub. API endpoint handlers have been refactored for improved performance and maintainability, with updated dependencies and import paths.

Changes

File Path Change Summary
apps/registry/lib/error/buildError.js Added error code constants, messages, and a function to build error objects.
apps/registry/lib/formatters/formatters.js Introduced various formatter functions for different data types.
apps/registry/lib/formatters/template.js Removed a specific theme from the export.
apps/registry/lib/generateResume.js Added a function to generate and format resumes, interacting with a database for caching.
apps/registry/lib/getResumeGist.js Introduced a function to fetch resume data from GitHub using Axios.
apps/registry/lib/schema.js Added a detailed JSON schema for resumes to standardize data.
apps/registry/pages/api/[payload].js Refactored API handler function, updated imports, and response handling.
apps/registry/pages/api/letter.js Updated ChatGPTAPI model version and settings.
apps/registry/pages/api/theme/[theme].js Updated import path for a module within the project structure.
apps/registry/pages/api/themes.js Updated import path for a constant to a different directory.

Tip

New Features and Improvements

Review Settings

Introduced new personality profiles for code reviews. Users can now select between "Chill" and "Assertive" review tones to tailor feedback styles according to their preferences. The "Assertive" profile posts more comments and nitpicks the code more aggressively, while the "Chill" profile is more relaxed and posts fewer comments.

AST-based Instructions

CodeRabbit offers customizing reviews based on the Abstract Syntax Tree (AST) pattern matching. Read more about AST-based instructions in the documentation.

Community-driven AST-based Rules

We are kicking off a community-driven initiative to create and share AST-based rules. Users can now contribute their AST-based rules to detect security vulnerabilities, code smells, and anti-patterns. Please see the ast-grep-essentials repository for more information.

New Static Analysis Tools

We are continually expanding our support for static analysis tools. We have added support for biome, hadolint, and ast-grep. Update the settings in your .coderabbit.yaml file or head over to the settings page to enable or disable the tools you want to use.

Tone Settings

Users can now customize CodeRabbit to review code in the style of their favorite characters or personalities. Here are some of our favorite examples:

  • Mr. T: "You must talk like Mr. T in all your code reviews. I pity the fool who doesn't!"
  • Pirate: "Arr, matey! Ye must talk like a pirate in all yer code reviews. Yarrr!"
  • Snarky: "You must be snarky in all your code reviews. Snark, snark, snark!"

Revamped Settings Page

We have redesigned the settings page for a more intuitive layout, enabling users to find and adjust settings quickly. This change was long overdue; it not only improves the user experience but also allows our development team to add more settings in the future with ease. Going forward, the changes to .coderabbit.yaml will be reflected in the settings page, and vice versa.

Miscellaneous

  • Turn off free summarization: You can switch off free summarization of PRs opened by users not on a paid plan using the enable_free_tier setting.
  • Knowledge-base scope: You can now set the scope of the knowledge base to either the repository (local) or the organization (global) level using the knowledge_base setting. In addition, you can specify Jira project keys and Linear team keys to limit the knowledge base scope for those integrations.
  • High-level summary placement: You can now customize the location of the high-level summary in the PR description using the high_level_summary_placeholder setting (default @coderabbitai summary).
  • Revamped request changes workflow: You can now configure CodeRabbit to auto-approve or request changes on PRs based on the review feedback using the request_changes_workflow setting.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Outside diff range and nitpick comments (2)
apps/registry/pages/api/themes.js (1)

Line range hint 5-9: Refactor to use for...of for better readability and performance.

- Object.keys(THEMES).forEach((value) => {
-   themes[value] = `https://registry.jsonresume.org/thomasdavis?theme=${value}`;
- });
+ for (const value of Object.keys(THEMES)) {
+   themes[value] = `https://registry.jsonresume.org/thomasdavis?theme=${value}`;
+ }
apps/registry/lib/formatters/template.js (1)

Line range hint 67-90: Convert the format function to an arrow function for consistency and modern JavaScript practices.

- const format = async function (resume, options) {
+ const format = async (resume, options) => {

This change aligns with modern JavaScript syntax and improves consistency across the codebase.

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between f60a1aa and f71095e.
Files ignored due to path filters (1)
  • apps/registry/package.json is excluded by !**/*.json
Files selected for processing (10)
  • apps/registry/lib/error/buildError.js (1 hunks)
  • apps/registry/lib/formatters/formatters.js (1 hunks)
  • apps/registry/lib/formatters/template.js (1 hunks)
  • apps/registry/lib/generateResume.js (1 hunks)
  • apps/registry/lib/getResumeGist.js (1 hunks)
  • apps/registry/lib/schema.js (1 hunks)
  • apps/registry/pages/api/[payload].js (1 hunks)
  • apps/registry/pages/api/letter.js (1 hunks)
  • apps/registry/pages/api/theme/[theme].js (1 hunks)
  • apps/registry/pages/api/themes.js (1 hunks)
Files skipped from review due to trivial changes (1)
  • apps/registry/lib/formatters/formatters.js
Additional Context Used
Biome (8)
apps/registry/lib/formatters/template.js (1)

67-90: This function expression can be turned into an arrow function.

apps/registry/lib/generateResume.js (1)

44-44: Change to an optional chain.

apps/registry/lib/getResumeGist.js (2)

14-14: Template literals are preferred over string concatenation.


41-42: Template literals are preferred over string concatenation.

apps/registry/pages/api/[payload].js (2)

33-35: Prefer for...of instead of forEach.


43-45: This else clause can be omitted because previous branches break early.

apps/registry/pages/api/letter.js (1)

42-42: This let declares a variable that is only assigned once.

apps/registry/pages/api/themes.js (1)

5-9: Prefer for...of instead of forEach.

Additional comments not posted (3)
apps/registry/pages/api/theme/[theme].js (1)

2-2: The updated import path enhances clarity and maintainability.

apps/registry/lib/error/buildError.js (1)

1-43: Structured error handling enhances maintainability and debuggability.

apps/registry/lib/schema.js (1)

1-521: Ensure the schema definitions are comprehensive and correctly formatted.

The JSON schema is well-structured and includes detailed descriptions and appropriate data types for various resume sections. This will facilitate accurate data validation and enhance data integrity.

apps/registry/lib/generateResume.js Outdated Show resolved Hide resolved
apps/registry/lib/generateResume.js Outdated Show resolved Hide resolved
Comment on lines 16 to 80
const generateResume = async (username, extension = 'template', query = {}) => {
const { theme } = query;
const formatter = formatters[extension];

if (!EXTENSIONS.has(extension)) {
return buildError(ERROR_CODES.INVALID_EXTENSION);
}

if (!formatter) {
return buildError(ERROR_CODES.UNKNOWN_FORMATTER);
}

// retrieve the users github gist
const { error: gistError, resume } = await getResumeGist(username);

if (gistError) {
return buildError(gistError);
}

const v = new Validator();
const validation = v.validate(resume, schema);

if (!validation.valid) {
return buildError(ERROR_CODES.RESUME_SCHEMA_ERROR, {
validation: validation.errors,
});
}

let selectedTheme = theme || (resume.meta && resume.meta.theme) || 'elegant';

selectedTheme = selectedTheme.toLowerCase();

// @todo - using as a resume cache for extra features
(async () => {
await supabase
.from('resumes')
.upsert(
{
username,
resume: JSON.stringify(resume),
updated_at: new Date(),
},
{ onConflict: 'username' }
)
.select();
})();

const options = { ...query, theme: selectedTheme, username };

let formatted = {};

try {
formatted = await formatter.format(resume, options);
} catch (e) {
console.error(e);
// @todo - do this better
if (e.message === 'theme-missing') {
return buildError(ERROR_CODES.TEMPLATE_MISSING);
}

return buildError(ERROR_CODES.UNKNOWN_TEMPLATE_ERROR);
}

return { content: formatted.content, headers: formatted.headers || [] };
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor the generateResume function to improve readability and maintainability.

- const generateResume = async (username, extension = 'template', query = {}) => {
+ async function generateResume(username, extension = 'template', query = {}) {

This change makes the function declaration more traditional and may improve readability for some developers.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const generateResume = async (username, extension = 'template', query = {}) => {
const { theme } = query;
const formatter = formatters[extension];
if (!EXTENSIONS.has(extension)) {
return buildError(ERROR_CODES.INVALID_EXTENSION);
}
if (!formatter) {
return buildError(ERROR_CODES.UNKNOWN_FORMATTER);
}
// retrieve the users github gist
const { error: gistError, resume } = await getResumeGist(username);
if (gistError) {
return buildError(gistError);
}
const v = new Validator();
const validation = v.validate(resume, schema);
if (!validation.valid) {
return buildError(ERROR_CODES.RESUME_SCHEMA_ERROR, {
validation: validation.errors,
});
}
let selectedTheme = theme || (resume.meta && resume.meta.theme) || 'elegant';
selectedTheme = selectedTheme.toLowerCase();
// @todo - using as a resume cache for extra features
(async () => {
await supabase
.from('resumes')
.upsert(
{
username,
resume: JSON.stringify(resume),
updated_at: new Date(),
},
{ onConflict: 'username' }
)
.select();
})();
const options = { ...query, theme: selectedTheme, username };
let formatted = {};
try {
formatted = await formatter.format(resume, options);
} catch (e) {
console.error(e);
// @todo - do this better
if (e.message === 'theme-missing') {
return buildError(ERROR_CODES.TEMPLATE_MISSING);
}
return buildError(ERROR_CODES.UNKNOWN_TEMPLATE_ERROR);
}
return { content: formatted.content, headers: formatted.headers || [] };
};
async function generateResume(username, extension = 'template', query = {}) {
const { theme } = query;
const formatter = formatters[extension];
if (!EXTENSIONS.has(extension)) {
return buildError(ERROR_CODES.INVALID_EXTENSION);
}
if (!formatter) {
return buildError(ERROR_CODES.UNKNOWN_FORMATTER);
}
// retrieve the users github gist
const { error: gistError, resume } = await getResumeGist(username);
if (gistError) {
return buildError(gistError);
}
const v = new Validator();
const validation = v.validate(resume, schema);
if (!validation.valid) {
return buildError(ERROR_CODES.RESUME_SCHEMA_ERROR, {
validation: validation.errors,
});
}
let selectedTheme = theme || (resume.meta && resume.meta.theme) || 'elegant';
selectedTheme = selectedTheme.toLowerCase();
// @todo - using as a resume cache for extra features
(async () => {
await supabase
.from('resumes')
.upsert(
{
username,
resume: JSON.stringify(resume),
updated_at: new Date(),
},
{ onConflict: 'username' }
)
.select();
})();
const options = { ...query, theme: selectedTheme, username };
let formatted = {};
try {
formatted = await formatter.format(resume, options);
} catch (e) {
console.error(e);
// @todo - do this better
if (e.message === 'theme-missing') {
return buildError(ERROR_CODES.TEMPLATE_MISSING);
}
return buildError(ERROR_CODES.UNKNOWN_TEMPLATE_ERROR);
}
return { content: formatted.content, headers: formatted.headers || [] };
}

apps/registry/pages/api/[payload].js Outdated Show resolved Hide resolved
`https://api.github.com/users/${username}/gists?per_page=100`,
{
headers: {
...(GITHUB_TOKEN ? { Authorization: 'Bearer ' + GITHUB_TOKEN } : {}), // If we have no token and are in development, we can still make some requests.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use template literals for string concatenation.

-          ...(GITHUB_TOKEN ? { Authorization: 'Bearer ' + GITHUB_TOKEN } : {}),
+          ...(GITHUB_TOKEN ? { Authorization: `Bearer ${GITHUB_TOKEN}` } : {}),

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
...(GITHUB_TOKEN ? { Authorization: 'Bearer ' + GITHUB_TOKEN } : {}), // If we have no token and are in development, we can still make some requests.
...(GITHUB_TOKEN ? { Authorization: `Bearer ${GITHUB_TOKEN}` } : {}), // If we have no token and are in development, we can still make some requests.

apps/registry/lib/getResumeGist.js Outdated Show resolved Hide resolved
@@ -33,7 +33,7 @@ export default async function handler(req, res) {

const api = new ChatGPTAPI({
apiKey: process.env.OPENAI_API_KEY,
model: 'gpt-3.5-32k-turbo',
model: 'gpt-4o',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const for variables that are not reassigned.

- let prompt = [
+ const prompt = [

Committable suggestion was skipped due low confidence.

@thomasdavis
Copy link
Member Author

@levino tried to move to app/[username]/route.js but it throws a hissy fit for themes importing react-dom so that needs some thinking. The tricky part being that react-dom is useful for so many things when developing themes and also running them standalone.

I wouldn't want to make theme development any worse than it is so the main idea is probably to use this flag -> https://nextjs.org/docs/app/api-reference/next-config-js/serverComponentsExternalPackages


On a previous note, I was considering using pages or app/page.js because when a theme errors, it makes it easy to pretty print a component to explain the error, as opposed to just a json error.


This PR mostly cleans up the code, and makes errors more consistent.

thomasdavis and others added 2 commits May 25, 2024 05:24
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
thomasdavis and others added 2 commits May 25, 2024 05:26
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between f71095e and dd0d614.
Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !pnpm-lock.yaml, !**/*.yaml
Files selected for processing (10)
  • .github/workflows/ci.yml (2 hunks)
  • README.md (5 hunks)
  • apps/registry/lib/generateResume.js (1 hunks)
  • apps/registry/lib/getResumeGist.js (1 hunks)
  • apps/registry/pages/api/[payload].js (1 hunks)
  • apps/registry/pages/api/suggestions.js (1 hunks)
  • apps/registry/playwright.config.js (1 hunks)
  • apps/registry/src/ui/Layout.js (1 hunks)
  • apps/registry/tests/render.spec.js (1 hunks)
  • themes/papirus/.eslintrc (1 hunks)
Files skipped from review due to trivial changes (4)
  • .github/workflows/ci.yml
  • apps/registry/pages/api/suggestions.js
  • apps/registry/tests/render.spec.js
  • themes/papirus/.eslintrc
Files skipped from review as they are similar to previous changes (1)
  • apps/registry/lib/generateResume.js
Additional Context Used
LanguageTool (8)
README.md (8)

Near line 7: Possible missing comma found.
Context: ...base templates, utils etc ## Apps All projects hosted on this domain, will be found in...
Rule ID: AI_HYDRA_LEO_MISSING_COMMA


Near line 96: Make sure that the noun ‘setup’ is correct. Did you mean the past participle “set up”?
Context: ...d be most applicable to you. It is not setup to be automated at the moment, and the ...
Rule ID: BE_VB_OR_NN


Near line 96: For conciseness, consider replacing this expression with an adverb.
Context: ...o you. It is not setup to be automated at the moment, and the formatting is garbage. Each po...
Rule ID: AT_THE_MOMENT


Near line 102: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: .../thomasdavis/jobs) ### Letter This is a very simple service that prompts GPT with your resu...
Rule ID: EN_WEAK_ADJECTIVE


Near line 110: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...davis/letter) ### Suggestions This is a very simple service that prompts GPT with your resu...
Rule ID: EN_WEAK_ADJECTIVE


Near line 116: This word is normally spelled as one.
Context: ...terview This is an implementation of a chat bot, your resume is injected, and the conve...
Rule ID: EN_COMPOUNDS_CHAT_BOT


Near line 116: Did you mean “yourself”? Remove the space in between.
Context: ...ded in the prompt. So you can interview your self or talk as if you were being interviewe...
Rule ID: YOUR_SELF_TO_YOURSELF


Near line 120: It appears that a hyphen is missing in the noun “to-do” (= task) or did you mean the verb “to do”?
Context: ...ocalhost:3000/thomasdavis/interview) # todo - AI tools - add an option to use yo...
Rule ID: TO_DO_HYPHEN

Markdownlint (8)
README.md (8)

120: null
Multiple top-level headings in the same document


18: null
Fenced code blocks should have a language specified


28: null
Fenced code blocks should have a language specified


34: null
Fenced code blocks should have a language specified


40: null
Fenced code blocks should have a language specified


46: null
Fenced code blocks should have a language specified


54: null
Fenced code blocks should have a language specified


80: null
Fenced code blocks should have a language specified

Biome (7)
apps/registry/lib/getResumeGist.js (1)

14-14: Template literals are preferred over string concatenation.

apps/registry/pages/api/[payload].js (1)

33-35: Prefer for...of instead of forEach.

apps/registry/playwright.config.js (4)

17-17: The computed expression can be simplified without the use of a string literal.


23-23: The computed expression can be simplified without the use of a string literal.


25-25: The computed expression can be simplified without the use of a string literal.


27-27: The computed expression can be simplified without the use of a string literal.

apps/registry/src/ui/Layout.js (1)

159-163: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Additional comments not posted (11)
apps/registry/pages/api/[payload].js (5)

1-1: LGTM! Importing generateResume aligns with the PR's focus on refactoring.


4-4: Refactored to use destructuring for req.query and handling of payload to determine username and extension. This simplifies the code and makes it more readable.

Also applies to: 9-9, 11-12


15-19: The use of generateResume here is a good example of modular code. It encapsulates the resume generation logic, which is a key part of this PR's objectives.


21-22: Proper error handling using the error object returned from generateResume. This ensures that errors are handled consistently, which is one of the PR's goals.


41-43: Simplified conditional rendering based on forceJSON. This makes the code cleaner and easier to understand.

apps/registry/lib/getResumeGist.js (2)

1-1: Import statements are correctly updated to include necessary modules.


7-52: The getResumeGist function is well-structured and handles errors effectively using buildError. It also uses template literals consistently, which improves readability.

apps/registry/playwright.config.js (1)

16-16: The configuration for the web server is correctly set to use environment variables for flexibility in different environments (like CI).

README.md (3)

9-11: Updated links provide direct access to the relevant directories within the GitHub repository, improving the documentation's usability.


Line range hint 44-68: The environment variables section is clearly documented, which is crucial for setting up the project correctly.


81-81: The command for starting the homepage app is correctly documented, facilitating easier project setup.

Comment on lines +33 to +35
headers.forEach((header) => {
res.setHeader(header.key, header.value);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor to use for...of for iterating over headers.

- headers.forEach((header) => {
-   res.setHeader(header.key, header.value);
- });
+ for (const header of headers) {
+   res.setHeader(header.key, header.value);
+ }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
headers.forEach((header) => {
res.setHeader(header.key, header.value);
});
for (const header of headers) {
res.setHeader(header.key, header.value);
}

@@ -158,7 +158,7 @@ export default function Layout({ children }) {

<script
async
data-id="101412887"
data-id="101412017"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script tag should be self-closing to adhere to JSX best practices.

- <script async data-id="101412017" src="https://static.getclicky.com/js"></script>
+ <script async data-id="101412017" src="https://static.getclicky.com/js" />

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
data-id="101412017"
<script async data-id="101412017" src="https://static.getclicky.com/js" />

@thomasdavis thomasdavis merged commit a958ca1 into master May 25, 2024
7 checks passed
@thomasdavis thomasdavis deleted the refactor-dynamic-resumes branch May 25, 2024 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant