Skip to content

Instantly share code, notes, and snippets.

@codewithsadee
Created September 22, 2025 18:26
Show Gist options
  • Select an option

  • Save codewithsadee/e60ef18142d09b2f8ca5ae991452a3bb to your computer and use it in GitHub Desktop.

Select an option

Save codewithsadee/e60ef18142d09b2f8ca5ae991452a3bb to your computer and use it in GitHub Desktop.
Bitblog
{
"semi": true,
"singleQuote": true,
"jsxSingleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"bracketSameLine": false,
"singleAttributePerLine": true,
"arrowParens": "always",
"endOfLine": "lf",
"overrides": [
{
"files": "*.html",
"options": {
"bracketSameLine": true,
"singleAttributePerLine": false
}
}
]
}
@import 'tailwindcss';
@import 'tw-animate-css';
@custom-variant dark (&:is(.dark *));
:root {
--background: hsl(48 33.3333% 97.0588%);
--foreground: hsl(44 19.4805% 15.098%);
--card: hsl(48 33.3333% 97.0588%);
--card-foreground: hsl(60 1.9608% 10%);
--popover: hsl(0 0% 100%);
--popover-foreground: hsl(50.7692 19.403% 13.1373%);
--primary: hsl(28 100% 50%);
--primary-foreground: hsl(0 0% 100%);
--secondary: hsl(46.1538 22.807% 88.8235%);
--secondary-foreground: hsl(50.7692 8.4967% 30%);
--muted: hsl(44 29.4118% 90%);
--muted-foreground: hsl(45 2.1739% 36.0784%);
--accent: hsl(46.1538 22.807% 88.8235%);
--accent-foreground: hsl(50.7692 19.403% 13.1373%);
--destructive: hsl(60 1.9608% 10%);
--destructive-foreground: hsl(0 0% 100%);
--border: hsl(50 7.5% 84.3137%);
--input: hsl(50.7692 7.9755% 68.0392%);
--ring: hsl(28 100% 50%);
--chart-1: hsl(27.7457 76.8889% 44.1176%);
--chart-2: hsl(251.4545 84.6154% 74.5098%);
--chart-3: hsl(46.1538 28.2609% 81.9608%);
--chart-4: hsl(256.5517 49.1525% 88.4314%);
--chart-5: hsl(28.1879 81.4208% 35.8824%);
--sidebar: hsl(51.4286 25.9259% 94.7059%);
--sidebar-foreground: hsl(60 2.521% 23.3333%);
--sidebar-primary: hsl(15.1111 55.5556% 52.3529%);
--sidebar-primary-foreground: hsl(0 0% 98.4314%);
--sidebar-accent: hsl(46.1538 22.807% 88.8235%);
--sidebar-accent-foreground: hsl(0 0% 20.3922%);
--sidebar-border: hsl(0 0% 92.1569%);
--sidebar-ring: hsl(0 0% 70.9804%);
--font-sans: Poppins, ui-sans-serif, sans-serif, system-ui;
--font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
'Liberation Mono', 'Courier New', monospace;
--radius: 0.5rem;
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 2px 4px -1px hsl(0 0% 0% / 0.1);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 4px 6px -1px hsl(0 0% 0% / 0.1);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 8px 10px -1px hsl(0 0% 0% / 0.1);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--tracking-normal: 0.025em;
--spacing: 0.25rem;
}
.dark {
--background: hsl(60 2.7027% 14.5098%);
--foreground: hsl(51.4286 25.9259% 94.7059%);
--card: hsl(60 2.7027% 14.5098%);
--card-foreground: hsl(48 33.3333% 97.0588%);
--popover: hsl(60 2.1277% 18.4314%);
--popover-foreground: hsl(60 5.4545% 89.2157%);
--primary: hsl(24.5815 94.9791% 53.1373%);
--primary-foreground: hsl(0 0% 100%);
--secondary: hsl(48 33.3333% 97.0588%);
--secondary-foreground: hsl(60 2.1277% 18.4314%);
--muted: hsl(60 3.8462% 10.1961%);
--muted-foreground: hsl(52 12.8205% 77.0588%);
--accent: hsl(48 9.8039% 10%);
--accent-foreground: hsl(51.4286 25.9259% 94.7059%);
--destructive: hsl(0 84.2365% 60.1961%);
--destructive-foreground: hsl(0 0% 100%);
--border: hsl(60 5.0847% 23.1373%);
--input: hsl(52.5 5.1282% 30.5882%);
--ring: hsl(24.5815 94.9791% 53.1373%);
--chart-1: hsl(24.8619 73.8776% 48.0392%);
--chart-2: hsl(251.4545 84.6154% 74.5098%);
--chart-3: hsl(48 9.8039% 10%);
--chart-4: hsl(248.2759 25.2174% 22.549%);
--chart-5: hsl(25.0685 75.2577% 38.0392%);
--sidebar: hsl(30 3.3333% 11.7647%);
--sidebar-foreground: hsl(46.1538 9.7744% 73.9216%);
--sidebar-primary: hsl(0 0% 20.3922%);
--sidebar-primary-foreground: hsl(0 0% 98.4314%);
--sidebar-accent: hsl(60 1.9608% 10%);
--sidebar-accent-foreground: hsl(46.1538 9.7744% 73.9216%);
--sidebar-border: hsl(0 0% 92.1569%);
--sidebar-ring: hsl(0 0% 70.9804%);
--font-sans: Poppins, ui-sans-serif, sans-serif, system-ui;
--font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
'Liberation Mono', 'Courier New', monospace;
--radius: 0.5rem;
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 2px 4px -1px hsl(0 0% 0% / 0.1);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 4px 6px -1px hsl(0 0% 0% / 0.1);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.1),
0 8px 10px -1px hsl(0 0% 0% / 0.1);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--font-serif: var(--font-serif);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--shadow-2xs: var(--shadow-2xs);
--shadow-xs: var(--shadow-xs);
--shadow-sm: var(--shadow-sm);
--shadow: var(--shadow);
--shadow-md: var(--shadow-md);
--shadow-lg: var(--shadow-lg);
--shadow-xl: var(--shadow-xl);
--shadow-2xl: var(--shadow-2xl);
--tracking-tighter: calc(var(--tracking-normal) - 0.05em);
--tracking-tight: calc(var(--tracking-normal) - 0.025em);
--tracking-normal: var(--tracking-normal);
--tracking-wide: calc(var(--tracking-normal) + 0.025em);
--tracking-wider: calc(var(--tracking-normal) + 0.05em);
--tracking-widest: calc(var(--tracking-normal) + 0.1em);
}
body {
letter-spacing: var(--tracking-normal);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
letter-spacing: var(--tracking-normal);
}
.tiptap {
@apply grow
outline-none;
h1,
h2,
h3 {
@apply font-semibold
tracking-tight
[&:not(:first-child)]:mt-6;
}
h1 {
@apply pb-2
text-3xl
first:mt-0;
}
h2 {
@apply text-2xl;
}
h3 {
@apply text-xl;
}
p {
@apply leading-7
[&:not(:first-child)]:mt-6;
}
blockquote {
@apply mt-6
border-l-2
pl-6;
}
hr {
@apply my-6;
}
ul {
@apply my-6
ml-6
list-disc
[&>li]:mt-2;
}
ol {
@apply my-6
ml-6
list-decimal
[&>li]:mt-2;
}
code {
@apply bg-muted
relative
rounded
px-[0.3rem]
py-[0.2rem]
font-mono;
}
.is-editor-empty:first-child {
@apply before:text-muted-foreground
before:content-[attr(data-placeholder)]
before:float-left
before:h-0
before:pointer-events-none;
}
}
}
@layer utilities {
.container {
@apply mx-auto
px-4
lg:px-6;
}
.section {
@apply py-6 md:py-10;
}
.section-title {
@apply text-xl font-semibold mb-4 md:text-2xl md:mb-6;
}
}
@layer components {
.nav-link.active {
@apply bg-accent;
}
}
/**
* @copyright 2025 codewithsadee
* @license Apache-2.0
*/
export interface User {
_id: string;
username: string;
email: string;
role: 'admin' | 'user';
firstName?: string;
lastName?: string;
socialLinks?: {
website?: string;
facebook?: string;
instagram?: string;
linkedin?: string;
x?: string;
youtube?: string;
};
createdAt: string;
updatedAt: string;
}
export interface Blog {
_id: string;
title: string;
slug: string;
content: string;
banner: {
url: string;
width: number;
height: number;
};
author: User;
viewsCount: number;
likesCount: number;
commentsCount: number;
status: 'draft' | 'published';
publishedAt: string;
updatedAt: string;
}
export interface Comment {
_id: string;
content: string;
likesCount: number;
user: User | null;
blog: Blog;
replies: Comment[];
createdAt: string;
updatedAt: string;
}
export type PaginatedResponse<T, K extends string> = {
limit: number;
offset: number;
total: number;
} & {
[key in K]: T[];
};
export type FieldValidationError = {
/**
* Indicates that the error occurred because a field had an invalid value
*/
type: 'field';
/**
* The location within the request where this field is
*/
location: Location;
/**
* The path to the field which has a validation error
*/
path: string;
/**
* The value of the field. It might be unset if the value is hidden.
*/
value?: string;
/**
* The error message
*/
msg: string;
};
export type ErrorCode =
| 'BadRequest'
| 'ValidationError'
| 'AuthenticationError'
| 'AuthorizationError'
| 'NotFound'
| 'ServerError';
export type ValidationError = {
code: ErrorCode;
errors: Record<string, FieldValidationError>;
};
export type ErrorResponse = {
code: ErrorCode;
message: string;
};
export interface ActionResponse<T = unknown> {
ok: boolean;
err?: ValidationError | ErrorResponse;
data?: T;
}
export interface AuthResponse {
accessToken: string;
user: Pick<User, 'username' | 'email' | 'role'>;
}
export interface BlogCreateResponse {
blog: Blog;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment