Skip to content

Commit fc3dfb9

Browse files
committed
Initial setup: Product-focused take-home assignment for senior full-stack engineers
- Ambiguous product requirements (no prescriptive UI specs) - Minimal API (no pagination, no filtering) to test problem-solving - Working Express server with mock data (5k orgs, 90 days DAU) - Rate limiting support via TWIST environment variable - AI usage documentation template - GitHub Actions for submission validation - Product engineer focus: requires decision-making and trade-off analysis
1 parent 7a424f8 commit fc3dfb9

File tree

15 files changed

+1676
-0
lines changed

15 files changed

+1676
-0
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Usage Analytics Submission
2+
3+
## Checklist
4+
5+
- [ ] Application runs successfully
6+
- [ ] Tests pass
7+
- [ ] AI_NOTES.md is filled out
8+
- [ ] README.md documents my decisions
9+
10+
## Summary
11+
12+
Brief description of your approach:
13+
14+
**Frontend framework:**
15+
16+
**Pagination strategy:**
17+
18+
**Key decisions:**
19+
20+
## Time Spent
21+
22+
Approximately ___ hours
23+
24+
## Questions for Discussion
25+
26+
List any questions or areas you'd like to discuss in the follow-up:
27+
28+
1.
29+
2.
30+
3.
31+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Check Submission
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
7+
jobs:
8+
validate:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Checkout code
13+
uses: actions/checkout@v4
14+
15+
- name: Check AI_NOTES.md exists
16+
run: |
17+
if [ ! -f "AI_NOTES.md" ]; then
18+
echo "❌ AI_NOTES.md is missing"
19+
exit 1
20+
fi
21+
echo "✅ AI_NOTES.md exists"
22+
23+
- name: Check AI_NOTES.md has content
24+
run: |
25+
# Count non-empty, non-comment lines
26+
CONTENT_LINES=$(grep -v '^#' AI_NOTES.md | grep -v '^<!--' | grep -v '^-->' | grep -v '^$' | wc -l)
27+
28+
if [ "$CONTENT_LINES" -lt 3 ]; then
29+
echo "❌ AI_NOTES.md appears to be empty or has minimal content"
30+
echo "Please document how you used AI during this assignment"
31+
exit 1
32+
fi
33+
34+
echo "✅ AI_NOTES.md has content ($CONTENT_LINES lines)"
35+
36+
- name: Check README.md updated
37+
run: |
38+
# Check if README has candidate's additions (look for common sections)
39+
if ! grep -q -i "decision\|trade-off\|approach\|choice" README.md; then
40+
echo "⚠️ README.md may not document your decisions"
41+
echo "Please add a section explaining your approach and trade-offs"
42+
else
43+
echo "✅ README.md appears to document decisions"
44+
fi
45+
46+
- name: Summary
47+
run: |
48+
echo "## Submission Validation ✅" >> $GITHUB_STEP_SUMMARY
49+
echo "" >> $GITHUB_STEP_SUMMARY
50+
echo "All required files are present and have content." >> $GITHUB_STEP_SUMMARY
51+
echo "" >> $GITHUB_STEP_SUMMARY
52+
echo "Next steps:" >> $GITHUB_STEP_SUMMARY
53+
echo "1. Reviewer will evaluate your submission" >> $GITHUB_STEP_SUMMARY
54+
echo "2. We'll schedule a follow-up discussion" >> $GITHUB_STEP_SUMMARY
55+

.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Dependencies
2+
node_modules/
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
7+
# Environment
8+
.env
9+
.env.local
10+
.env.*.local
11+
12+
# OS
13+
.DS_Store
14+
Thumbs.db
15+
16+
# IDE
17+
.vscode/
18+
.idea/
19+
*.swp
20+
*.swo
21+
*~
22+
23+
# Build outputs
24+
dist/
25+
build/
26+
.next/
27+
out/
28+
29+
# Logs
30+
logs/
31+
*.log
32+
33+
# Testing
34+
coverage/
35+
.nyc_output/
36+
37+
# Misc
38+
*.bak
39+
*.tmp
40+

AI_NOTES.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# AI Usage Notes
2+
3+
Document how you used AI during this assignment.
4+
5+
## Format
6+
7+
Each entry should include:
8+
- What you asked the AI
9+
- What you got back
10+
- What you modified/verified
11+
- Why you made changes
12+
13+
## Example
14+
15+
**Prompt:** "Create a date range picker component in React"
16+
17+
**Response:** AI generated a basic component with date-fns library
18+
19+
**Edits:** Changed to use native input type="date" for simplicity and better mobile support
20+
21+
**Verification:** Tested edge cases (invalid dates, reversed ranges, boundary dates)
22+
23+
---
24+
25+
## Your Notes
26+
27+
<!-- Add your entries below -->
28+

AI_NOTES_EXAMPLE.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# AI Usage Notes - Example
2+
3+
This is an example of what good AI_NOTES.md documentation looks like.
4+
5+
**Note:** This is just a reference to help you understand the format. You should fill out `AI_NOTES.md` with your own entries, not copy this file.
6+
7+
---
8+
9+
## Entry 1: Project Setup
10+
11+
**Prompt:** "Create a React app with Vite and TypeScript for a data analytics dashboard"
12+
13+
**Response:** AI provided commands to initialize Vite project with React and TypeScript template
14+
15+
**Edits:** None - used the commands as-is
16+
17+
**Verification:** Ran `npm create vite@latest` and confirmed project structure was correct
18+
19+
---
20+
21+
## Entry 2: Date Range Picker Component
22+
23+
**Prompt:** "Create a React component for selecting a date range with start and end dates, default to last 14 days"
24+
25+
**Response:** AI generated a component using react-datepicker library with state management
26+
27+
**Edits:**
28+
- Removed react-datepicker dependency (too heavy)
29+
- Changed to native HTML5 date inputs for simplicity
30+
- Added validation to ensure end date is after start date
31+
- Added keyboard navigation support
32+
33+
**Verification:**
34+
- Tested with various date ranges
35+
- Tested edge cases (same date, reversed dates, future dates)
36+
- Verified keyboard navigation works
37+
- Checked mobile behavior
38+
39+
---
40+
41+
## Entry 3: CSV Export Function
42+
43+
**Prompt:** "Create a function to export table data to CSV format and trigger download"
44+
45+
**Response:** AI generated function using Blob and URL.createObjectURL
46+
47+
**Edits:**
48+
- Added proper CSV escaping for fields with commas
49+
- Added header row with column names
50+
- Changed to only export currently visible/filtered data (not all data)
51+
- Added filename with timestamp
52+
53+
**Verification:**
54+
- Tested export with various data
55+
- Tested with special characters (commas, quotes)
56+
- Verified file downloads correctly
57+
- Opened CSV in Excel to verify format
58+
59+
---
60+
61+
## Entry 4: Error Boundary
62+
63+
**Prompt:** "Create a React error boundary component to catch rendering errors"
64+
65+
**Response:** AI generated class component with componentDidCatch
66+
67+
**Edits:**
68+
- Added retry button to error UI
69+
- Added error logging (console.error)
70+
- Improved error message to be user-friendly
71+
- Added fallback UI that matches app design
72+
73+
**Verification:**
74+
- Tested by throwing error in child component
75+
- Verified error boundary catches it
76+
- Verified retry button works
77+
- Checked that error doesn't crash entire app
78+
79+
---
80+
81+

GETTING_STARTED.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Getting Started
2+
3+
Welcome! This guide will help you get set up quickly.
4+
5+
## Quick Setup
6+
7+
### 1. Start the API Server
8+
9+
```bash
10+
cd server
11+
npm install
12+
npm start
13+
```
14+
15+
You should see:
16+
```
17+
Generating mock data...
18+
Generated 5000 organizations
19+
Generated 90 days of DAU data
20+
API server running on http://localhost:3001
21+
```
22+
23+
### 2. Test the APIs
24+
25+
```bash
26+
# In a new terminal
27+
curl http://localhost:3001/api/metrics/dau
28+
curl http://localhost:3001/api/metrics/top-orgs
29+
```
30+
31+
### 3. Build Your Frontend
32+
33+
```bash
34+
# Create your frontend directory
35+
mkdir frontend
36+
cd frontend
37+
38+
# Use your preferred setup
39+
# Examples:
40+
npm create vite@latest . # Vite (React, Vue, Svelte, etc.)
41+
npx create-next-app@latest . # Next.js
42+
npx create-react-app . # Create React App
43+
# ... or any other framework
44+
```
45+
46+
## What You're Building
47+
48+
A single-page "Usage Analytics" dashboard that helps answer:
49+
- **"How is our DAU trending over time?"**
50+
- **"Which organizations are most active?"**
51+
52+
You'll need to decide:
53+
- How to visualize DAU trends
54+
- How to present organization data effectively
55+
- What interactions users need
56+
- How to handle edge cases and errors
57+
58+
## Available APIs
59+
60+
**GET /api/metrics/dau**
61+
- Returns daily active user data
62+
- Call it to see the response format
63+
64+
**GET /api/metrics/top-orgs**
65+
- Returns organizations ranked by activity
66+
- Call it to see the response format
67+
68+
Explore these endpoints to understand what data is available.
69+
70+
## What to Submit
71+
72+
1. **Working application** - We should be able to run it
73+
2. **Tests** - At least 2 meaningful test cases
74+
3. **AI_NOTES.md** - Document how you used AI (see AI_NOTES_EXAMPLE.md for format)
75+
4. **README.md** - Update with your decisions, trade-offs, and what you'd do with more time
76+
77+
## Tips
78+
79+
- **Time:** Aim for 2-3 hours. Don't spend more than this.
80+
- **Framework:** Use whatever you're most comfortable with.
81+
- **AI:** Feel free to use AI! Just document it in AI_NOTES.md.
82+
- **Backend:** The server code is available if you want to explore or modify it.
83+
- **Questions:** If anything is unclear, please ask!
84+
85+
## Submission
86+
87+
When you're done:
88+
1. Create a PR with your changes
89+
2. Fill out the PR template
90+
3. We'll review and schedule a follow-up discussion
91+
92+
## Need Help?
93+
94+
- Check `AI_NOTES_EXAMPLE.md` for documentation format
95+
- Look at `server/routes/metrics.js` to understand the API
96+
- The server code is clean and modifiable - feel free to explore
97+
98+
Good luck! 🚀
99+

0 commit comments

Comments
 (0)