Skip to content

Instantly share code, notes, and snippets.

View SanichKotikov's full-sized avatar
🤔
Working...

Sanich SanichKotikov

🤔
Working...
View GitHub Profile
@SanichKotikov
SanichKotikov / component-feature-architecture-skill.md
Created August 2, 2026 19:46
Component-Feature architecture skill
name component-feature-architecture
description Use when organizing or reasoning about code layout — deciding where a new piece of code belongs, structuring folders and files, understanding or enforcing the Component-Feature Architecture scheme, or checking which components may import each other. Triggers on "folder structure", "where should this code go", "component", "feature", "code layout", "architecture", "dependencies between modules". Do NOT use for framework-specific APIs, naming conventions, or import ordering.

Component-Feature Architecture

A component-first code layout: the project is a collection of components (pieces from which the project is assembled), grouped into features by domain. A component lives at feature/segment/component. File structure is a consequence of the architecture, not the cause — first understand the components and their interaction rules, then the folder layout emerges from that.

Level 1 — Feature

@SanichKotikov
SanichKotikov / functional-architecture-skill.md
Created August 2, 2026 19:44
Functional architecture skill
name functional-architecture
description Use when analyzing, designing, writing, refactoring, or reviewing code architecture — deciding whether a piece of code is Data, Computations, or Actions, separating pure functions from side effects, placing smart vs dumb components, or structuring a codebase. Triggers on "pure function", "side effects", "smart/dumb components", "data layer", "SRP", "responsibility", "architecture", "refactoring". Do NOT use for framework-specific APIs, project-specific naming, or any non-architecture task.

Functional Architecture

A code-architecture approach based on three categories: Data, Computations, and Actions. The goal is to minimize risk by keeping these categories strictly separate, pushing code "down" toward pure computations, and containing side effects in well-defined places.

Core model

import boundariesPlugin from 'eslint-plugin-boundaries';
export default {
plugins: {
boundaries: boundariesPlugin,
},
settings: {
'boundaries/elements': [
// segments
{ type: 'type', pattern: 'src/*/type/**' },
@SanichKotikov
SanichKotikov / use-list-state.ts
Last active February 8, 2025 08:42
useListState hook for React
import { type SetStateAction, useMemo, useRef, useState } from "react";
type TListState<T extends object, K extends keyof T, U extends T[K]> = [
items: T[],
handlers: Readonly<{
list: () => T[];
has: (id: U) => boolean;
add: (item: T) => void;
concat: (items: T[]) => void;
clear: VoidFunction;
// utils/types.ts
type KeysOfType<O, T> = { [K in keyof O]: O[K] extends T ? K : never }[keyof O];
// utils/array.ts
function inAbcOrderBy<T extends object, K extends KeysOfType<T, string>>(prop: K) {
return (a: T, b: T): number => {
return (a[prop] as string).localeCompare(b[prop] as string);
};
}
for file in *; do
if [ -f "$file" ]; then
if [ "$file" = "convert_images.sh" ];
then
continue
fi
sips -s format heic -s formatOptions 100 $file --out ./
fi
done
import { createElement, lazy, useEffect, useMemo, ComponentType, ReactElement } from 'react';
export function withAwaitData<T extends {}, K extends keyof T, P extends T[K][]>(
component: ComponentType<T>,
fetcher: (...args: P) => Promise<void>,
keys?: K[],
): (props: T) => ReactElement<T>;
export function withAwaitData<T extends {}, K extends keyof T, P extends T[K][]>(
component: ComponentType<T>,
fetcher: (...args: P) => Promise<void>,
import React, {useEffect, useState, useCallback} from 'react';
import Sticky from 'react-stickynode';
type TFilter = {
name: string;
value: string;
component: React.ReactElement;
};
interface IProps {
function calc(num: number, lines: number = 3) {
const step = (num + (num * 2 / 100)) / lines;
const shift = 10 ** (Math.ceil(Math.log10(Math.ceil(step) + 1)) - 2);
return Math.floor((Math.ceil(step / shift) * shift) * 10) / 10;
}
function round(num: number, low: number) {
return Math.max(calc(num), calc(low * -1));
}
const URL = 'https://www.google-analytics.com/collect';
export function ga(category: string, action: string) {
return new Promise((res) => {
const data = {
v: 1,
tid: 'UA-XXXXX-Y',
t: 'event',
ec: category,
ea: action,