diff --git a/components.d.ts b/components.d.ts
index 8524af64..3e65c3cc 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -129,22 +129,20 @@ declare module '@vue/runtime-core' {
     MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
     MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
     MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
-    NA: typeof import('naive-ui')['NA']
     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
-    NCode: typeof import('naive-ui')['NCode']
+    NCheckbox: typeof import('naive-ui')['NCheckbox']
     NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
     NConfigProvider: typeof import('naive-ui')['NConfigProvider']
+    NDivider: typeof import('naive-ui')['NDivider']
     NEllipsis: typeof import('naive-ui')['NEllipsis']
-    NFormItem: typeof import('naive-ui')['NFormItem']
     NH1: typeof import('naive-ui')['NH1']
     NH3: typeof import('naive-ui')['NH3']
     NIcon: typeof import('naive-ui')['NIcon']
-    NInputNumber: typeof import('naive-ui')['NInputNumber']
     NLayout: typeof import('naive-ui')['NLayout']
     NLayoutSider: typeof import('naive-ui')['NLayoutSider']
     NMenu: typeof import('naive-ui')['NMenu']
-    NScrollbar: typeof import('naive-ui')['NScrollbar']
-    NSpin: typeof import('naive-ui')['NSpin']
+    NSpace: typeof import('naive-ui')['NSpace']
+    NTable: typeof import('naive-ui')['NTable']
     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']
@@ -154,6 +152,8 @@ declare module '@vue/runtime-core' {
     PhoneParserAndFormatter: typeof import('./src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue')['default']
     QrCodeGenerator: typeof import('./src/tools/qr-code-generator/qr-code-generator.vue')['default']
     RandomPortGenerator: typeof import('./src/tools/random-port-generator/random-port-generator.vue')['default']
+    RegexMemo: typeof import('./src/tools/regex-memo/regex-memo.vue')['default']
+    'RegexMemo.content': typeof import('./src/tools/regex-memo/regex-memo.content.md')['default']
     RegexTester: typeof import('./src/tools/regex-tester/regex-tester.vue')['default']
     ResultRow: typeof import('./src/tools/ipv4-range-expander/result-row.vue')['default']
     RomanNumeralConverter: typeof import('./src/tools/roman-numeral-converter/roman-numeral-converter.vue')['default']
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 647257f9..388cfaf4 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -10,6 +10,7 @@ import { tool as safelinkDecoder } from './safelink-decoder';
 import { tool as xmlToJson } from './xml-to-json';
 import { tool as jsonToXml } from './json-to-xml';
 import { tool as regexTester } from './regex-tester';
+import { tool as regexMemo } from './regex-memo';
 import { tool as markdownToHtml } from './markdown-to-html';
 import { tool as pdfSignatureChecker } from './pdf-signature-checker';
 import { tool as numeronymGenerator } from './numeronym-generator';
@@ -158,6 +159,7 @@ export const toolsByCategory: ToolCategory[] = [
       yamlViewer,
       emailNormalizer,
       regexTester,
+      regexMemo,
     ],
   },
   {
diff --git a/src/tools/regex-memo/index.ts b/src/tools/regex-memo/index.ts
new file mode 100644
index 00000000..43d63676
--- /dev/null
+++ b/src/tools/regex-memo/index.ts
@@ -0,0 +1,12 @@
+import { BrandJavascript } from '@vicons/tabler';
+import { defineTool } from '../tool';
+
+export const tool = defineTool({
+  name: 'Regex cheatsheet',
+  path: '/regex-memo',
+  description: 'Javascript Regex/Regular Expression cheatsheet',
+  keywords: ['regex', 'regular', 'expression', 'javascript', 'memo', 'cheatsheet'],
+  component: () => import('./regex-memo.vue'),
+  icon: BrandJavascript,
+  createdAt: new Date('2024-09-14'),
+});
diff --git a/src/tools/regex-memo/regex-memo.content.md b/src/tools/regex-memo/regex-memo.content.md
new file mode 100644
index 00000000..0f779401
--- /dev/null
+++ b/src/tools/regex-memo/regex-memo.content.md
@@ -0,0 +1,121 @@
+### Normal characters
+
+Expression | Description
+:--|:--
+`.` or `[^\n\r]` | any character *excluding* a newline or carriage return
+`[A-Za-z]` | alphabet
+`[a-z]` | lowercase alphabet
+`[A-Z]` | uppercase alphabet
+`\d` or `[0-9]` | digit
+`\D` or `[^0-9]` | non-digit
+`_` | underscore
+`\w` or `[A-Za-z0-9_]` | alphabet, digit or underscore
+`\W` or `[^A-Za-z0-9_]` | inverse of `\w`
+`\S` | inverse of `\s`
+
+### Whitespace characters
+
+Expression | Description
+:--|:--
+` ` | space
+`\t` | tab
+`\n` | newline
+`\r` | carriage return
+`\s` | space, tab, newline or carriage return
+
+### Character set
+
+Expression | Description
+:--|:--
+`[xyz]` | either `x`, `y` or `z`
+`[^xyz]` | neither `x`, `y` nor `z`
+`[1-3]` | either `1`, `2` or `3`
+`[^1-3]` | neither `1`, `2` nor `3`
+
+- Think of a character set as an `OR` operation on the single characters that are enclosed between the square brackets.
+- Use `^` after the opening `[` to “negate” the character set.
+- Within a character set, `.` means a literal period.
+
+### Characters that require escaping
+
+#### Outside a character set
+
+Expression | Description
+:--|:--
+`\.` | period
+`\^` | caret
+`\$` | dollar sign
+`\|` | pipe
+`\\` | back slash
+`\/` | forward slash
+`\(` | opening bracket
+`\)` | closing bracket
+`\[` | opening square bracket
+`\]` | closing square bracket
+`\{` | opening curly bracket
+`\}` | closing curly bracket
+
+#### Inside a character set
+
+Expression | Description
+:--|:--
+`\\` | back slash
+`\]` | closing square bracket
+
+- A `^` must be escaped only if it occurs immediately after the opening `[` of the character set.
+- A `-` must be escaped only if it occurs between two alphabets or two digits.
+
+### Quantifiers
+
+Expression | Description
+:--|:--
+`{2}` | exactly 2
+`{2,}` | at least 2
+`{2,7}` | at least 2 but no more than 7
+`*` | 0 or more
+`+` | 1 or more
+`?` | exactly 0 or 1
+
+- The quantifier goes *after* the expression to be quantified.
+
+### Boundaries
+
+Expression | Description
+:--|:--
+`^` | start of string
+`$` | end of string
+`\b` | word boundary
+
+- How word boundary matching works:
+    - At the beginning of the string if the first character is `\w`.
+    - Between two adjacent characters within the string, if the first character is `\w` and the second character is `\W`.
+    - At the end of the string if the last character is `\w`.
+
+### Matching
+
+Expression | Description
+:--|:--
+`foo\|bar` | match either `foo` or `bar`
+`foo(?=bar)` | match `foo` if it’s before `bar`
+`foo(?!bar)` | match `foo` if it’s *not* before `bar`
+`(?<=bar)foo` | match `foo` if it’s after `bar`
+`(?
+import { useThemeVars } from 'naive-ui';
+import Memo from './regex-memo.content.md';
+
+const themeVars = useThemeVars();
+
+
+
+  
+    
+  
+
+
+
diff --git a/src/tools/regex-tester/index.ts b/src/tools/regex-tester/index.ts
index c6bd412a..957d665c 100644
--- a/src/tools/regex-tester/index.ts
+++ b/src/tools/regex-tester/index.ts
@@ -8,5 +8,5 @@ export const tool = defineTool({
   keywords: ['regex', 'tester', 'sample', 'expression'],
   component: () => import('./regex-tester.vue'),
   icon: Language,
-  createdAt: new Date('2024-04-20'),
+  createdAt: new Date('2024-09-14'),
 });
diff --git a/src/tools/regex-tester/regex-tester.vue b/src/tools/regex-tester/regex-tester.vue
index 0054c8f6..a1fa7958 100644
--- a/src/tools/regex-tester/regex-tester.vue
+++ b/src/tools/regex-tester/regex-tester.vue
@@ -101,9 +101,9 @@ watchEffect(
         rows="3"
         :validation="regexValidation"
       />
-      
-        See documentation on regular-expressions.info
-      
+      
+        See Regular Expression Cheatsheet
+      
       
         
           Global search. (g)