@lioncho7 오호 피그마 구독까지 정리하셨다는 게 인상 깊네요. 직접 기획부터 라이브 서비스까지 하시나봐요.
저도 1인 사이드 프로젝트는 그렇게 운영하는데 회사 단위는 아무래도 책임도 있고... 개발자 분들이 더 잘 아시다보니.. 회사에서는 기획에 한정되서 진행하고 있네요.
요즘 AI를 이용해 기획하면서 제일 귀찮았던 게... 프로토타입 만들어놓고 화면정의서를 화면마다 쓰는거였어요.
그래서 프로토타입 자체가 화면정의서가 되면 안 되나? 싶어 라이브러리로 만들어봤습니다.
기획 업계분들 한번 써보시고 불편한 거 있으면 편하게 피드백 주세요, 고쳐볼게요 🙂
버핏이 CNBC에서 구글 얘기한 2분이 요즘 AI capex 논쟁 전체를 정리함.
"구글이랑 경쟁자들 전부 수천억 달러를 깔고 있다. 그건 진짜 돈이다. 우리 철도 개발에도 그런 돈은 안 들어갔다. 소프트웨어 시절엔 없던 게임이다."
자산 가벼울 땐 안 사더니 capex 무거워서 주주들이 싫어하는 지금 샀냐는 질문엔 — "기록을 보면 이 회사들이 월스트리트가 파는 물건의 90~95%보다 승자가 될 확률이 높다. 월스트리트 보고서 중에 기업의 실제 내부수익률을 파고드는 걸 본 적이 없다. 다음 분기 얘기만 묻는다. 우스운 일이다."
버크셔는 이 판에 310억달러를 얹었음. 어제 구글 FCF가 22년 만에 처음 마이너스가 된 바로 그 지출을, 버핏은 사야 할 이유로 읽는 중.
The US government, citing national security authorities, has issued an export control directive to suspend all access to Fable 5 and Mythos 5 by any foreign national, whether inside or outside the United States, including foreign national Anthropic employees.
The net effect of this order is that we must abruptly disable Fable 5 and Mythos 5 for all our customers to ensure compliance.
Access to all other Claude models is not affected.
We apologize for this disruption to our customers. We believe this is a misunderstanding and are working to restore access as soon as possible.
Read our full statement: https://t.co/bwn0sximKZ
As a result of a US government directive, we are suspending access to Claude Fable 5 for all users. You can continue to use all other Claude models.
Here’s what this means for you:
Across Claude products, new sessions will run on your selected default model or Opus 4.8, and existing Fable 5 sessions will end with an error.
On the Claude Platform, requests to Fable 5 will also return an error. Please update your integrations to other Claude models.
We know this is a disruption to your workflows; we appreciate your patience and support.
@bumpeng27 저도 리짜이밍 옹호하는건 아닙니다만, 원래 자본주의 사회에서 눈치보면서 사는게 맞지 않나요? 님들도 상사가 뭐 시켯는데 좀 이상하면 철학 도덕 자격 운운하면서 안할건가요? 그냥 시장이 원하면 하는거고 그게 내 인생줄 연명하는거죠. 뭐 직장인, 전문경영인과 하는거 크게 다르지 않아보이는데
New fun thing I did to secure my VPS even further
I installed @Cloudflare Tunnel, many of you recommended me this
I already had 443 inbound firewall limited to Cloudflare's IP range, but this is even better
Cloudflare Tunnel is outbound, which means it connects from your server to Cloudflare, and keeps the connection active, then if someone opens your site, Cloudflare sends you the package via the tunnel and your server responds
Then you can block ALL inbound traffic on your firewall (in my case the Hetzner firewall in the dashboard), so now NOBODY can ever access my server, only Cloudflare and Tailscale (which is my own subnet which just my server and my laptop on it)
You can just ask AI to set it up on the server etc., very easy
✅ Done
💳 Made an auto-dispute response system for Interior AI to see how easy it'd be
It syncs old disputes but also catches new disputes via Stripe webhook and then auto submits evidence to try win them, it even includes the interior designs they generated in the evidence PDF to prove they used it!
Here's the prompt/skill I made:
----
Build an auto-dispute-response system for Stripe that:
1. Shared evidence collection (app/dispute_evidence.php)
Create a shared file with functions used by both the webhook and sync worker. This avoids duplicating evidence logic.
Key functions:
- getDisputeUserPlan($user, $stripe) — pulls the user's subscription plan from Stripe API (source of truth, since local DB plan field gets cleared on cancellation). Falls back to local DB fields if Stripe call fails. Maps product IDs to plan names and includes price/interval and canceled status.
- collectDisputeEvidence($stripe, $user, $email, $charge, $photosDb) — collects all text and file evidence, returns an array ready to submit to Stripe.
- generateServiceDocPdf($stripe, $user, $email, $photos_done, $recent_photos, $total_amount_paid) — generates a PDF with customer info, usage summary, recent activity table, and up to 6 actual product images (resized to JPEG at 500px wide / quality 75 to stay under Stripe's 5MB file upload limit). Returns both the Stripe file ID and raw PDF data.
Important: pull total_amount_paid from Stripe charges API (sum of succeeded, non-refunded charges) instead of trusting the local DB which can be null/stale.
2. Webhook handler (in stripe_webhook.php)
Catch `charge.dispute.created` events. When a dispute comes in:
- Get the dispute, charge, and customer objects from Stripe
- Look up the user in the local database by stripe_customer_id
- Save the dispute to a `disputes` SQLite database (fields: dispute_id, charge_id, payment_intent_id, stripe_customer_id, user_id, email, amount, currency, reason, status, epoch_created, epoch_evidence_submitted, evidence_json, stripe_response, epoch_resolved, outcome)
- Call collectDisputeEvidence() to collect all evidence (text + file uploads)
- Submit evidence to Stripe via $stripe->disputes->update($dispute_id, ['evidence' => $evidence])
- Send a Telegram notification that a new dispute came in and evidence was auto-submitted
Also catch `charge.dispute.updated` and `charge.dispute.closed` events to track dispute outcomes (won/lost) in the database and send Telegram notifications with the result (with emoji: checkmark for won, x for lost, warning for other).
3. Evidence fields submitted to Stripe
TEXT fields (write strings directly):
- product_description — describe what the product/service is
- customer_name — from Stripe customer object
- customer_email_address — from Stripe customer object
- access_activity_log — detailed usage log: signup date, number of items/actions done, last active date, subscription plan (from Stripe), platform, total amount paid (from Stripe), recent activity with timestamps
- uncategorized_text — the "why we should win" argument: customer signed up on X, actively used the service doing Y things, total amount paid, service was delivered digitally/instantly, customer never contacted us for a refund before disputing
- refund_policy_disclosure — when the refund policy was presented (during checkout, always accessible at /legal)
- cancellation_policy_disclosure — when cancellation policy was shown (during checkout, accessible at /legal, can cancel anytime from dashboard)
- refund_refusal_explanation — customer didn't contact us for a refund before filing the dispute
- cancellation_rebuttal — proof customer actively used the service and never requested cancellation
- service_date — date of the charge (Y-m-d format)
FILE UPLOAD fields (upload file to Stripe first via $stripe->files->create(['purpose'=>'dispute_evidence', 'file'=>fopen($path,'r')]), then pass the returned file_xxxxx ID):
- receipt — pull the invoice PDF directly from Stripe ($stripe->invoices->retrieve($charge->invoice)->invoice_pdf gives a ready-made PDF URL, just download it and upload as dispute evidence)
- service_documentation — generate a PDF containing: customer info section, service usage summary, recent activity table, and up to 6 actual product images/screenshots the customer received. Resize images before embedding (500px wide, JPEG quality 75) to stay under Stripe's 5MB file upload limit.
Also save both PDFs to your file storage (e.g. Cloudflare R2, S3) with hashed filenames so they're not guessable but viewable from the admin dashboard.
Store the storage URLs in the evidence_json as _receipt_r2_url and _service_doc_r2_url (underscore prefix so they're easy to identify as internal fields).
DO NOT use these fields for text — they expect file upload IDs only:
service_documentation, cancellation_policy, refund_policy, customer_communication, customer_signature, receipt, shipping_documentation, duplicate_charge_documentation, uncategorized_file
4. CLI sync worker (workers/syncDisputes.php)
A script that pulls ALL existing disputes from Stripe's API (paginated with $stripe->disputes->all(['limit' => 100]) and starting_after for pagination), saves them to the local disputes database, and for any that still have needs_response or warning_needs_response status and haven't had evidence submitted yet — auto-submits evidence using the shared collectDisputeEvidence() function. This is needed because the webhook only catches future disputes, not existing ones. Too heavy to run on frontend — run via CLI only (php workers/syncDisputes.php). Saves a JSON cache file with sync results so the dashboard can show last sync time.
5. Mini dashboard (disputes.php with ?key= auth)
A simple HTML page protected by ?key= query parameter that shows:
- Stats boxes: total disputes, pending, won, lost, disputed last 30 days (amount + count), disputed last 12 months (amount + count), total $ disputed
- A note showing the CLI sync command and last sync time from cache
- A test form where you enter a stripe_customer_id to preview what evidence would be submitted (without actually submitting) — useful for debugging
- A table of all disputes: date, email, amount, reason, status (color-coded badges), evidence submission status, links to both detail view and Stripe dashboard
Detail view (action=view&id=dispute_id):
- Shows all dispute info, link to Stripe, and a "Regenerate Evidence" button
- Shows PDF file links (receipt + service documentation) if available
- Shows Stripe file upload IDs
- Shows all text evidence fields
Regenerate Evidence (action=regen&id=dispute_id):
- Regenerates the receipt and service documentation PDFs and uploads to file storage
- Updates the evidence_json in the database with new PDF URLs
- IMPORTANT: Use fastcgi_finish_request() to send the HTTP response immediately (redirect back to detail page with "regenerating in background" notice), then continue generating PDFs in the background. This prevents frontend timeouts since downloading images and generating PDFs can take 30+ seconds.
Add an nginx rewrite for the page (e.g. rewrite ^/disputes/?$ /disputes.php). Make sure it's in the correct nginx config file (check which one the symlink in sites-enabled actually points to).
6. Telegram notifications
- New dispute: "{site name} - New dispute from {email} for ${amount} ({reason}). Evidence auto-submitted to Stripe. {stripe_dashboard_link}"
- Evidence failed: "{site name} - New dispute from {email} for ${amount} ({reason}). Evidence submission FAILED: {error}"
- Dispute won: "{site name} - Dispute WON (checkmark) for {email} - ${amount} ({reason}) {stripe_dashboard_link}"
- Dispute lost: "{site name} - Dispute LOST (x) for {email} - ${amount} ({reason}) {stripe_dashboard_link}"
- DB permission error: "{site name} - DISPUTE DB ERROR: {error} - check permissions on data/disputes.db"
7. Make sure these Stripe webhook events are enabled in the Stripe dashboard:
- charge.dispute.created
- charge.dispute.updated
- charge.dispute.closed
8. Database permissions
The disputes.db file must be writable by the web server user (e.g. www-data). If you create it from CLI as root, fix ownership to match your other DB files. PHP-FPM runs as a different user than root.
9. Dependencies
- FPDF (setasign/fpdf) for PDF generation — install via composer require setasign/fpdf
- GD extension for image resizing (usually already installed)
- Stripe PHP SDK (already installed if you have Stripe webhooks)
- AWS S3 SDK for R2/S3 uploads (already installed if using Cloudflare R2)
꼬빌은 사는 그 당시에는 남는게 없는데 몇년 지나면 임대료가 계속 올라서 미래에 남는답니다. (그게 아니면 살 이유 없음)
제가 2019년에 매입햇는데 지금은 그때보다 월세가 80% 정도 올랏죠. (수익률도)
매매가도 미래의 인플레이션을 한 몇년 땡겨와서 받아요. (서울 중심지일수록)
ㄹㅇ... 2~300억 넘어가는 꽉 찬 메디컬, 또는 본인 사업체 실사용 아닌 이상
꼬빌 투자는 지옥 그 잡채다...
꼬빌 투자할 정도의 현금흐름, 에쿼티 가진 사람들 상황이 대부분 비슷할 텐데
걍 인생을 여기다 걸어야 함...ㅋㅋㅋ
코로나 이전에 산 사람들조차 워낙 싸게 사서 가격 많이 오르긴 했지만
그때 산 사람도 지금 시장에서 버티기가 쉽지 않음...